This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
HTTP GET with request body
I've read few discussions here which do not advocate sending content via HTTP GET. There are restrictions on the size of data that can be sent via clients (web browsers). And handling GET data also depends on servers. Please refer section Resources below.
However, I've been asked to test the possibility to send content via HTTP GET using RestTemplate. I refered few discussions on spring forum but they were not answered. (Please note sending data via http Post works fine). The discussion here suggests using POST instead.
dev env - JBoss AS 5.1, Spring 3.1.3
Client
#Test
public void testGetWithBody()
{
// acceptable media type
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.TEXT_PLAIN);
// header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
// body
String body = "hello world";
HttpEntity<String> entity = new HttpEntity<String>(body, headers);
Map<String, Object> uriVariables = new HashMap<String, Object>();
uriVariables.put("id", "testFile");
// Send the request as GET
ResponseEntity<String> result = restTemplate.exchange(
"http://localhost:8080/WebApp/test/{id}/body",
HttpMethod.GET, entity, String.class, uriVariables);
Assert.assertNotNull(result.getBody());
}
Server #Controller
#RequestMapping(value = "/{id}/body", method = RequestMethod.GET)
public #ResponseBody
String testGetWithBody(#PathVariable String id,
#RequestBody String bodyContent)
{
return id + bodyContent;
}
The problem -
executing this test case returns 500 Internal Server Error. On debugging, I found that the controller is not hit.
Is it correct to understand that the RestTemplate provides the way to send data as request body, but the error occurs because the server could not handle the request body ?
If the request body sent via HTTP Get is not conventional why does RestTemplate provide the APIs to allow sending it ? Does this mean there are few servers capable of handling the Request body via GET ?
Resources - discussions on sending body via HTTP GET using RestTemplate at spring forum
http://forum.springsource.org/showthread.php?129510-Message-body-with-HTTP-GET&highlight=resttemplate+http+get
http://forum.springsource.org/showthread.php?94201-GET-method-on-RestTemplate-exchange-with-a-Body&highlight=resttemplate+http+get
Resources - General discussions on sending body via HTTP GET
get-with-request-body
is-this-statement-correct-http-get-method-always-has-no-message-body
get-or-post-when-reading-request-body
http-uri-get-limit
Is it correct to understand that the RestTemplate provides the way to send data as request body, but the error occurs because the server could not handle the request body ?
You can tell by looking at network traffic (does the request get sent with a request body and a GET method?) and at server logs (the 500 result you receive must have a server-side effect that gets logged, and if not, configure the server to do so).
If the request body sent via HTTP Get is not conventional why does RestTemplate provide the APIs to allow sending it ? Does this mean there are few servers capable of handling the Request body via GET ?
Because it is a generic class that also allows you to craft requests that can include a message body.
As stated in HTTP GET with request body:
In other words, any HTTP request message is allowed to contain a message body, and thus [a server] must parse messages with that in mind. Server semantics for GET, however, are restricted such that a body, if any, has no semantic meaning to the request. The requirements on parsing are separate from the requirements on method semantics.
A body on a GET cannot do anything semantically, because you are requesting a resource. It's like you tell the server: "Give me resource X, oh, and have some apples!". The server won't care about your apples and happily serve resource X - or throw an error because it doesn't like any offers in a request.
However, I've been asked to test the possibility to send content via HTTP GET
Please tell the one who requested this that this is a case that should not have to be tested, because no sensible implementation supports it.
Related
I have seen people use NewRequest() method of the "net/http" package for testing APIs. Why not use the NewRequest() method from "net/http/httptesting"? What's the difference? Documentation advises the following:
// To generate a client HTTP request instead of a server request, see
// the NewRequest function in the net/http package.
What would be the difference in handling cookies, for example? Both seem to be very similar.
TL;DR: they're the same type, used a bit differently for two use cases and initialized differently to serve these use cases
The difference is only in usage - they are the same type http.Request. http.NewRequest is used for the more "production" use case which is client - "create a new request to send to the server". When writing HTTP servers, it's occasionally useful to create requests for testing, which is what httptest.NewRequest does. The doc of http.NewRequest is helpful here:
NewRequest returns a Request suitable for use with Client.Do or
Transport.RoundTrip. To create a request for use with testing a Server
Handler, either use the NewRequest function in the net/http/httptest
package, use ReadRequest, or manually update the Request fields. See
the Request type's documentation for the difference between inbound
and outbound request fields.
If you check the docs of the http.Request type, you'll find things like:
// URL specifies either the URI being requested (for server
// requests) or the URL to access (for client requests).
//
// For server requests, the URL is parsed from the URI
// supplied on the Request-Line as stored in RequestURI. For
// most requests, fields other than Path and RawQuery will be
// empty. (See RFC 7230, Section 5.3)
//
// For client requests, the URL's Host specifies the server to
// connect to, while the Request's Host field optionally
// specifies the Host header value to send in the HTTP
// request.
URL *url.URL
Note the "For client requests" vs. "For server requests".
If you see a place that doesn't use httptest.NewRequest it could be because:
They're not aware of it
Or they need more careful fine-tuning that http.NewRequest doesn't provide
Hello everybody I'm trying to do a simple HTTP call to a Tomcat Server running on my server from my Android App. The server will then execute a certain command to my website. I created a button that when I click it runs the HTTP call from the App.
If I use the approach below, it opens the browser on my phone to run this HTTP. Is it possible to do something similar but not have my app open the browser???
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://" + IP + ":8080/server/run.jsp"));
startActivity(browserIntent);
thank you so much in advance :D
Of course it starts your browser. Your code is explicitly asking Android to launch an app that can "view" the URL.
If you want your app to access the URL directly, use HttpURLConnection instead:
1.Obtain a new HttpURLConnection by calling URL.openConnection() and casting the result to HttpURLConnection.
2.Prepare the request. The primary property of a request is its URI. Request headers may also include metadata such as credentials, preferred content types, and session cookies.
3.Optionally upload a request body. Instances must be configured with setDoOutput(true) if they include a request body. Transmit data by writing to the stream returned by getOutputStream().
4.Read the response. Response headers typically include metadata such as the response body's content type and length, modified dates and session cookies. The response body may be read from the stream returned by getInputStream(). If the response has no body, that method returns an empty stream.
5.Disconnect. Once the response body has been read, the HttpURLConnection should be closed by calling disconnect(). Disconnecting releases the resources held by a connection so they may be closed or reused.
I am new to servelts programming. and Just today, I started learning it. and I am a little bit confused concerning
HttpServletRequest. it is written in a tutorial that, the class doGET() has some methods such as form "query" data, HTTP request headers, and the client’s hostname.
As far as I understood, the HttpServletRequest is something like a protocol allows the SERVER to
receive a request from the CLIENT side. My question is, Why the CLIENT side is interesting in
knowing something like the client’s host-name or HTTP request headers.
If you found the question is silly please do not vote my question down, because I do not want to lose this account with stack overflow.
First of all HttpServletRequest is an interface implemented by your Servlet Container.
HttpServlet is a convenience class which your Servlet can extend from and get hold of all the HTTP specific methods. doGet() is one such method to process the GET requests.
HttpServletRequest is something like a protocol allows the SERVER to receive a request from the CLIENT side
HTTP is a request-response protocol. Your container forms a HttpServletRequest object from the actual request received by the Web Server and forwards it to your Servlet's service() method.
Why the CLIENT side is interesting in
knowing something like the client’s host-name or HTTP request headers.
If you are talking about Servlets, it is always executed in server side . Hence, methods like request.getHeader() is used by the Servlet to read headers from the request sent by the client. These headers provide some extra information about the request (or response).Many of the headers associated with a request are handled by the server itself. Take, for example, how a server restricts access to its documents. The server uses HTTP headers, and servlets need not know the details. When a server receives a request for a restricted page, it checks that the request includes an appropriate Authorization header that contains a valid username and a password. If it doesn't, the server itself issues a response containing a WWW-Authenticate header, to tell the browser its access to a resource was denied. When the client sends a request that includes the proper Authorization header, the server grants the access and gives any servlet invoked access to the user's name via the getRemoteUser() call.
Read HTTP Made Really Easy, An Overview of Request Headers.
On a project I am doing I have been forced into developing a server side part due to restrictions of the "Same Origin Policy" in browsers, that prevents the AJAX making requests to anything outside of the domain of the page.
Therefore I am building a Java Servlet that will act as the handler for the page and will retrieve XML's from external sites and return it back to the client page using AJAX
I will use GET parameters to instruct the servlet what URL to fetch XMLs from.
I am a beginner with Java, I could easily do this in PHP but sadly there are no environments availale to host PHP or Apache
Skeleton Code
public void doGet(HttpServletRequest agentRequest, HttpServletResponse agentResponse)
throws ServletException, IOException
{
agentResponse.setContentType("text/xml");
//determine if agentRequest is for templateList or templateDetails
//build URL for specific request
//if no parameters sent or invalid send error response
//fetch XML from URL
//output response XML to client
}
I do not want a full code solution, just references and ideas to get me in the right direction!
e.g. what java features to use for this, etc.
Thanks
As requested, some high-level ideas to get you started:
Firstly, get the external URL from the request parameter:
//equivalent of PHP $_GET["url"]
String externalUrl = agentRequest.getParameter("url");
Then you need to retrieve the response from the external URL. There are already various Q'a and A's on that topic, including How do I do a HTTP GET in Java?
Finally, you need to write the response into your response using the OutputStream supplied:
agentResponse.getOutputStream();
I have:
Request request = new Request(Method.GET, "https://www.awebsite.com/login");
Client client = new Client(Protocol.HTTPS);
Response response = client.handle(request);
...
response.getEntity().write(System.out);
But I don't know how to set the login parameters...
I want code that
does the escaping etc
can switch between get/post easily
Being a REST-based platform, I'm thinking I might need to use some parameter "representation" but that seems a bit strange. I'd think it would be common enough to build in this representational exception.
If by "login parameters" you mean sending credentials using Basic HTTP Authentication, it's done using Request.setChallengeResponse() like so:
Request request = new Request(Method.GET, "https://www.awebsite.com/login");
request.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_BASIC, username, password));
This will work for any Request, using any HTTP method.
If, however, the server to which you're trying to authenticate expects credentials using some protocol other than Basic HTTP Auth, then you'll need to explain that protocol -- i.e. does it use cookies, headers, tokens, etc.
BTW, you might get faster/better responses by posting to the Restlet-Discuss mailing list; I've been on there for a year and a half and it's a great community.