I'm trying to create simple REST request handler like this:
#RequestMapping(value = "test", method = RequestMethod.GET)
public String test(#RequestParam(name = "test", required = false) String test,
#RequestParam(name ="number", required = false) Long number) {
return new StringBuilder(test).append(" ").append(number).toString();
}
But when I test this by CURL:
curl http://localhost:8080/test?test=abc&number=2016
The output become like this:
abc null
What's wrong here? Is this my mistake or Spring bug?
I'm using Spring Boot 1.4.0 (latest version may be).
curl version is 7.43.0 (64 bit).
Hopefully this is the solution and not a false assumption:
If you really type:
curl http://localhost:8080/test?test=abc&number=2016
Your curl process
curl http://localhost:8080/test?test=abc
will be executed and send in the background because of the &.
Try:
curl 'http://localhost:8080/test?test=abc&number=2016'.
Used curl from cmder on Windows 8.1. Got same issue with multiple Spring #RequestParam annotations. Wrapping url in single quotes did't fix it for me, but double quotes worked as expected.
No quotes approach:
curl http://localhost:8080/jobs/test%20name/find?jobTime=jobtime&jobDate=jobdate
Will produce 400 Bad request error, because jobDate parameter marked as mandatory in Spring controller.
Single quotes approach:
curl 'http://localhost:8080/jobs/test%20name/find?jobTime=jobtime&jobDate=jobdate'
Will produce 'jobDate' is not recognized as an internal or external command, operable program or batch file. error
Double quotes will behave as expected:
curl "http://localhost:8080/jobs/test%20name/find?jobDate=jobdate&jobTime=jobtime"
Produced correct output from controller class.
Same exact GET request working fine without any quotes if executed via browser address bar.
Related
I'm trying to execute a POST request using curl in order to do some authorization. The expected result is a token which will be provided in the Location response header
Issue
If I execute the command from within my bash, it'll work just fine (= with redirections etc.)
If I execute the exact same command (really just copy&paste) in my Java application, I get a slightly different result ( = missing token in the Location response header)
Expected result
Token located in the Location response header, like Location: /https://localhost:4200/token=123
Actual result
Some kind of error, like Location: my.policy
Command
This is the basic structure of the command. Basically, it is a POST request with some redirection involved.
curl -L -v --header \"something:special\” --cookie \"a=1;b=2\" --data \"param1¶m2\" https://url
What I've tried
Enabled the verbose mode via -v
Enabled redirection via -L
Checked for handshake (or common) errors
Checked for typos and encoding issues
Executed command within the bash
Tried executing the command using a Java based approach
Even tried to execute the command creating a bash from within the code and passing the command
Java code
String command = "SOME CURL COMMAND USING POST"
// execute the command
Process process = Runtime.getRuntime().exec(command);
// Since we will get a 302 (as expected), the result will be in the error stream
Scanner scanner = new Scanner(process.getErrorStream());
// Do some formatting...
String tmp = "";
while (scanner.hasNext()) {
String t = scanner.next();
if (t.equals("*") || t.equals("<") || t.equals(">")) {
tmp += "\n";
}
tmp += t + " ";
}
System.out.println("Content" + tmp);
Question
Is Java handling the execution differently? Because I don't see why I get a different result
Any help is appreciated.
Best
I'm struggling with path param encoding with retrofit:
http://localhost:8080/nuxeo/api/v1 is my base url.
I have this Call #GET("path/{documentPath}")
Call<Document> fetchDocumentByPath(#Path("documentPath") String docPath);
As param, I'm setting the following: default-domain/blabla
I run the query against my tomcat app and I get this answer
Response{protocol=http/1.1, code=400, message=Bad Request, url=http://localhost:8080/nuxeo/api/v1/path/default-domain%2Fblabla}
Even if I put encode = true to say "don't encode my parameter, it's already encoded", it's still encoding it.
Moreover, in retrofit, this test retrofit2.RequestBuilderTest#getWithEncodedPathParam doesn't work if we put Request request = buildRequest(Example.class, "po/ng"); with the following assertion: assertThat(request.url().toString()).isEqualTo("http://example.com/foo/bar/po/ng/");
Tomcat has restricted his URL validation for security reason: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-0450.
So I'd like to send '/' directly in my path parameter without encoding it in %2F. How can I achieve it?
Thank you!
Since parent-2.0.0-beta4, the parameter of the annotation of #Path is now working properly.
Confirmed the following in Curl:
This is working fine-
curl -X GET 'http://remoteUrl.com:8080/public/private/request/data?begin=12&end=20'
This is not working-
curl -X GET http://remoteUrl.com:8080/public/private/request/data?begin=12&end=20
So the whole purpose is to use the way first curl command in a java code with restlet to send the paramters in a GET request but unfortunately my code is not working.
Code:
ClientResource clientResource = new
ClientResource("http://remoteUrl.com:8080/public/private/request/
data?begin=12&end=20");
Representation clientText = clientResource.get();
Error Log:
INFO: Unable to read a header
java.io.IOException: Parameter or extension has no name. Please check your value
at org.restlet.engine.header.HeaderReader.readNamedValue(HeaderReader.java:499)
at org.restlet.engine.header.CacheDirectiveReader.readValue(CacheDirectiveReader.java:65)
at org.restlet.engine.header.CacheDirectiveReader.readValue(CacheDirectiveReader.java:38)
at org.restlet.engine.header.HeaderReader.addValues(HeaderReader.java:282)
at org.restlet.engine.header.CacheDirectiveReader.addValues(CacheDirectiveReader.java:50)
at org.restlet.engine.header.HeaderUtils.copyResponseTransportHeaders(HeaderUtils.java:776)
at org.restlet.engine.adapter.ClientAdapter.readResponseHeaders(ClientAdapter.java:129)
at org.restlet.engine.adapter.ClientAdapter.updateResponse(ClientAdapter.java:191)
at org.restlet.engine.adapter.ClientAdapter.commit(ClientAdapter.java:105)
at org.restlet.engine.adapter.HttpClientHelper.handle(HttpClientHelper.java:119)
at org.restlet.Client.handle(Client.java:153)
From the exception you give in your question, it seems that the value of the header Cache-Control isn't correct within the response. Restlet isn't able to parse it.
I guess that the value of this header is an empty string in the response...
Could you give us in your question the exact content of the response (mainly headers)?
Hope it helps you,
Thierry
This question already has answers here:
HTTP GET with request body
(23 answers)
Closed 7 years ago.
I don't understand why this curl invocation gives me a 400 bad request.
curl -v -XGET -H "Content-Type:application/json" -d '{"match":{"first":"james"}}' http://localhost:8080/geocon/search/
Considered that this is the code part who should handle everything
#Path(Paths.SEARCH)
public class SearchService {
#GET
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String search(#DefaultValue(NO_TYPE) #QueryParam("type") String type, String query) {
// do interesting stuff with the query
System.out.println(type);
System.out.println(query);
return //the result of the query
}
Obviously, I don't see in the console the two print lines and the answer from the web service is 400 Bad request
If I change the verb in curl and in the code (POST instead of GET), the results are OK and everything works as it should.
Why?
Can't I use GET passing data? If you think about it, I am not modifying stuff, I'd just receive data so GET should be the most RESTful translation for it.
You are allowed to send a body with a GET request, but it must not have any semantics; it should essentially be ignored. Not doing so violates the HTTP/1.1 specification. I suggest avoiding this practice because no one expects a request body with a GET request.
Now I'm not sure if the MVC framework you're using is stricter in the sense that it automatically rejects any GET request sent with a body, because in general a server can accept a GET request with a body, but is just supposed to ignore it.
Hence, what you're doing is not RESTful. The only way you can pass in data through a GET is through query parameters.
UPDATE
This is in response to your comment.
You could expose an explicit resource called searchResult or search. To create a searchResult or search resource instance, you pass in a body that is essentially a query. If you are using semantic media types (as you should for proper RESTfulness), your search-result resource could have the media type application/vnd.myservice.search-result+json and the query can have the media type application/vnd.myservice.search-query+json. Then, you can POST a request to /searchResults that has a request body that contains the complex query. The media-type of the response would be application/vnd.myservice.search-result+json and it can contain the search results.
So how does this play out? A search query comes in and you parse out the body and run the query. Then you should persist the results (not for ever; give it some sane TTL value). Once you have done that, you return a 303 See Other with a Location header that has a link to the search results (maybe something like /searchResults/4334, where 4334 is the id of this particular result). The client can then access this URI to retrieve the search results. If the client requests a search result that has expired (i.e., the server cleaned it up because the TTL expired), then the server should respond with a 410 Gone.
Also read this for more pointers.
It seems that syntax you are using has a typo.Try using the below ones for json and xml format. -XGET is wrong. it should be -X GET.
For xml
curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://hostname/resource
For JSON
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://hostname/resource
I have a rest endpoint as below. pid is UUID which I'm parsing using UUID.fromString(pid);
#GET
#Path("/")
public Response process(#Context HttpServletRequest req,
#QueryParam("p") String pid,
#DefaultValue("3") #QueryParam("a") String active,
#DefaultValue("3") #QueryParam("c") String closed,
#CookieParam("X") String cookie) {
//my stuff
}
This is not setting 'p' and 'X' when I run jetty and curl using
curl localhost:9090/rest/accounts?p=<uuid>&c=4&a=5 -b "X=1212;"
response is -b: command not found
it works when I move cookie part to front
curl -b "X=1212;" localhost:9090/rest/accounts?p=&c=4&a=5
but 'c' and 'a' are always 3 (default).
Is there something wrong with the way I'm using it.
Your shell probably interpreted &, try:
curl -b "X=1212;" "localhost:9090/rest/accounts?p=&c=4&a=5"
If you want to see detail information about request and response use:
curl -v -b "X=1212;" "localhost:9090/rest/accounts?p=&c=4&a=5"