I would like to take value of specific parameter in query string. Is there any method in HttpClient which can do if for me (ex. util class method) or I have to write my own?
In 4.X.X there is:
List<NameValuePair> parameters = URLEncodedUtils.parse(new URI(
request.getRequestLine().getUri()), HTTP.UTF_8);
for (NameValuePair nameValuePair : parameters) {
System.out.println(nameValuePair.getName() + ": "
+ nameValuePair.getValue());
}
Then handle your own parameter.
Related
I'm writing a unit test for a controller method that accepts a MultipartFile
and a custom object MessageAttachment. So far I can see that the MultipartFile is the correct format for the request but the MessageAttachment is not.
The parsing of the messageAttachment throws a server side 500 error with MethodArgumentConversionNotSupportedException.
It seem to be an issue with converting the MessageAttachment to a MockMultipartFile in the test. This is similar to the example shown here - https://stackoverflow.com/a/21805186
Question:
How can you resolve a MethodArgumentConversionNotSupportedException with MockMvc?
Controller method under test
#RequestMapping(value = "/", method = RequestMethod.POST, consumes = "multipart/form-data", produces = "application/json")
public ResponseEntity<MessageAttachment> handleFileUpload(#RequestParam(value = "file", required = true) MultipartFile file, #RequestParam(value = "messageAttachment") MessageAttachment messageAttachment) {
//do stuff with the file and attachment passed in..
MessageAttachment attachment = new MessageAttachment();
return ResponseEntity.accepted().header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + file.getOriginalFilename() + "\"").body(attachment);
}
MockMvc Test
#Test
public void shouldSaveUploadedFile() throws Exception {
// Given
ObjectMapper mapper = new ObjectMapper();
MessageAttachment messageAttachment = new MessageAttachment();
messageAttachment.setTimestamp(new Date());
MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain",
"Spring Framework".getBytes());
//Mapping the msgAttachment to a MockMultipartFile HERE
MockMultipartFile msgAttachment = new MockMultipartFile("messageAttachment", "","application/json",
mapper.writeValueAsString(messageAttachment).getBytes());
// When
this.mockMvc.perform(MockMvcRequestBuilders.multipart("/media/")
.file(multipartFile)
.file(msgAttachment)).andDo(MockMvcResultHandlers.print());
}
Console output of MockMvcResultHandlers.print()
MockHttpServletRequest:
HTTP Method = POST
Request URI = /media/
Parameters = {}
Headers = {Content-Type=[multipart/form-data]}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.fizz.buzz.fizzapi.controller.MediaUploadController
Method = public org.springframework.http.ResponseEntity<com.fizz.buzz.fizzapi.model.MessageAttachment> com.fizz.buzz.fizzapi.controller.MediaUploadController.handleFileUpload(org.springframework.web.multipart.Mu
ltipartFile,com.fizz.buzz.fizzapi.model.MessageAttachment,javax.servlet.http.HttpServletRequest)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
You'll want to use #RequestPart instead of #RequestParam for the part of the request that is application/json. The javadoc for #RequestPart states
Supported method argument types include MultipartFile in conjunction
with Spring's MultipartResolver abstraction,
javax.servlet.http.Part in conjunction with Servlet 3.0 multipart
requests, or otherwise for any other method argument, the content of
the part is passed through an HttpMessageConverter taking into
consideration the 'Content-Type' header of the request part. This is
analogous to what #RequestBody does to resolve an argument based on
the content of a non-multipart regular request.
Note that #RequestParam annotation can also be used to associate the
part of a "multipart/form-data" request with a method argument
supporting the same method argument types. The main difference is that
when the method argument is not a String, #RequestParam relies on type
conversion via a registered Converter or PropertyEditor while
#RequestPart relies on HttpMessageConverters taking into consideration
the 'Content-Type' header of the request part. #RequestParam is likely
to be used with name-value form fields while #RequestPart is likely to
be used with parts containing more complex content (e.g. JSON, XML).
Presumably, you haven't registered a Converter, nor a PropertyEditor, to parse the content of that part, whereas an HttpMessageConverter for JSON is automatically registered (depending on your Spring MVC/Boot version) if you have Jackson on the classpath.
I want to setup an endpoint for testing webhooks from third parties. Their documentation is uniformly poor and there is no way ahead of time to tell exactly what I will be getting. What I've done is setup an ApiController that will just take a request and add a row to a table with what they are sending. This lets me at least verify they are calling the webhook, and to see the data so I can program to it.
// ANY api/webook/*
[Route("{*path}")]
public ActionResult Any(string path)
{
string method = Request.Method;
string name = "path";
string apiUrl = Request.Path;
string apiQuery = Request.QueryString.ToString();
string apiHeaders = JsonConvert.SerializeObject(Request.Headers);
string apiBody = null;
using (StreamReader reader = new StreamReader(Request.Body))
{
apiBody = reader.ReadToEnd();
}
Add(method, name, apiUrl, apiQuery, apiHeaders, apiBody);
return new JsonResult(new { }, JsonSettings.Default);
}
This works great, except for this new webhook I am usign that posts as form data so some middleware is reading the body and it ends up null in my code. Is there any way to disable the model processing so I can get at the request body?
You could actually use model binding to your advantage and skip all that stream reading, using the FromBody attribute. Try this:
[Route("{*path}")]
[HttpPost]
public ActionResult Any(string path, [FromBody] string apiBody)
I want to modify HTTP request URI and HTTP request method using a CXF interceptor in a HTTP client.
I have developed something like this:
public class MyInterceptor extends AbstractPhaseInterceptor<Message> {
public MyInterceptor() {
super(Phase.PRE_PROTOCOL);
}
public void handleMessage(Message message) {
// this returns me correct path and method
// String path = (String) message.getExchange().getOutMessage().get(Message.REQUEST_URI);
// String method = (String) message.getExchange().getOutMessage().get(Message.HTTP_REQUEST_METHOD);
// this does not work as expected
String path = (String) message.get(Message.REQUEST_URI);
String method = (String) message.get(Message.HTTP_REQUEST_METHOD);
// do things here
}
}
Why do need I to use exchange/OutMessage to obtain data about current message and I can not use message directly?
How can I edit both values? I tried using message.put(<key>, <value>) and the same with exchange/OutMessage, but nothing is modified.
Coming to the path, you'd always get that value as null, I believe.
You can try following code, to get the actual value of your uri:
String requestURI = (String) message.get(Message.class.getName() + ".REQUEST_URI");
I had an url pattern like this:
http://xy.com/param1/value1/param2/value2/..../paramN/valueN
I would like to write a #RequestMapping in Spring colntroller, but I don't know how can I do if I don't know how many param and value will be.
Is there any way to get all params and values to collection?
Or can anybody helpme how to fix this?
Thanks
Why can't you use the standard way without #PathVariables at all? So url will be like
http://xy.com?param1=value1¶m2=value2&....¶mN=valueN
and your annotation as:
#RequestMapping("xyz1")
#ResponseBody
public String index(#RequestParam(required = false) String param1, #RequestParam(required = false) String param2,
#RequestParam(required = false) String paramN) {
return "Param1=" + param1 + ", Param2=" + param1 + ", ParamN=" + paramN;
}
#RequestMapping("xyz2")
#ResponseBody
public String index2(HttpServletRequest servletRequest) {
StringBuilder result = new StringBuilder();
for (Entry<String, String[]> entry : servletRequest.getParameterMap().entrySet()) {
result.append(entry.getKey());
result.append('=');
result.append(Arrays.toString(entry.getValue()));
result.append(", ");
}
return result.toString();
}
where #RequestParam is used when all the expected parameters are known and servletRequest.getParameterMap() is used if you really need to handle them dynamically.
Or you can go the hackish way with really optional #PathVariables that is described here.
I was use Spring ModelAttribute instead of
.Net's System.Web.HttpUtility class defines the following function to parse a query string into a NameValueCollection:
public static NameValueCollection ParseQueryString(string query);
Is there any function to do the reverse (i.e. to convert a NameValueCollection into a query string)?
System.Collections.Specialized.NameValueCollection does NOT support this, but a derived internal class System.Web.HttpValueCollection DOES (by overriding ToString()).
Unfortunately (being internal) you cannot instantiate this class directly, but one is returned by HttpUtility.ParseQueryString() (and you can call this with String.Empty, but not Null).
Once you have a HttpValueCollection, you can fill it from your original NameValueCollection by calling Add(), before finally calling ToString().
var nameValueCollection = new NameValueCollection {{"a","b"},{"c","d"}};
var httpValueCollection = System.Web.HttpUtility.ParseQueryString(String.Empty);
httpValueCollection.Add(nameValueCollection);
var qs = httpValueCollection.ToString();
nameValueCollection.ToString() = "System.Collections.Specialized.NameValueCollection"
httpValueCollection.ToString() = "a=b&c=d"
A NameValueCollection has an automatic ToString() method that will write all your elements out as a querystring automatically.
you don't need to write your own.
var querystringCollection = HttpUtility.ParseQueryString("test=value1&test=value2");
var output = querystringCollection.ToString();
output = "test=value1&test=value2"
I found that a combination of UriBuilder and HttpUtility classes meets my requirements to manipulate query parameters. The Uri class on its own is not enough, particularly as its Query property is read only.
var uriBuilder = new UriBuilder("http://example.com/something?param1=whatever");
var queryParameters = HttpUtility.ParseQueryString(uriBuilder.Query);
queryParameters.Add("param2", "whatever2");
queryParameters.Add("param3", "whatever2");
uriBuilder.Query = queryParameters.ToString();
var urlString = uriBuilder.Uri.ToString();
The above code results in the URL string: http://example.com/something?param1=whatever¶m2=whatever2¶m3=whatever2
Note that the ToString() goes via a Uri property, otherwise the output string would have an explicit port 80 in it.
It's nice to be able to do all this using framework classes and not have to write our own code.
I don't think there is a built in one, but here is an example of how to implement http://blog.leekelleher.com/2008/06/06/how-to-convert-namevaluecollection-to-a-query-string/
Here are 2 very useful functions that I use all the time:
private string GetQueryStringParameterValue(Uri url, string key)
{
return HttpUtility.ParseQueryString(url.Query.TrimStart('?'))[key];
}
private Uri SetQueryStringParameterValue(Uri url, string key, string value)
{
var parameters = HttpUtility.ParseQueryString(url.Query.TrimStart('?'));
parameters[key] = value;
var uriBuilder = new UriBuilder(url) { Query = parameters.ToString() };
return uriBuilder.Uri;
}