How to access content at the server end? - java

I have used the following code in my client:
HttpPost post = new HttpPost(url);
post.setEntity(new ByteArrayEntity(myString.getBytes("UTF8")));
HttpResponse response = this.execute(post);
I would now like to access the string on the server end. The handle method looks as follows:
public void handle(String target, Request baseRequest, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException { ... }
The request only lets me access the content length and type but not the content itself. Any pointers?
I'm using java as a pl and the built in classes from javax.servlet.

You've set the string as the sole HTTP request body instead of as a request parameter for some reason. So, to get it, you need to read the whole HTTP request body. This is in the servlet available by
InputStream input = request.getInputStream();
// Read it into a String the usual way (using UTF-8).
Note that this would return an empty stream when it's already been read beforehand, e.g. by calling getParameter() beforehand on the very same request which would implicitly parse the POST request body for that.
The more sane approach would be to send it as a normal URL encoded request parameter as follows (exactly like as those HTML forms by default do)
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("myString", myString));
post.setEntity(new UrlEncodedFormEntity(params));
so that you can in the servlet just do
String myString = request.getParameter("myString");
// ...

Related

Java servlet can't receive the parts of an http post multipart request

First, I asked this question What did I miss to send a http part post request and it seems i didn't understand the logic of sending multipart from a client to a server. Using this post https://developer.constantcontact.com/docs/mylibrary-files-api/file-add-multipart-post.html I was able t see the required fields in each part.
I build my request and added all the required fields as you see here
HttpClient client = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(
"http://localhost:8080/ServletExample1/multipart1");
httpPost.addHeader("Content-Type",
"multipart/related; boundary=HereItGoes");
httpPost.addHeader("Accept", MediaType.TEXT_PLAIN);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
FileBody bin = new FileBody(new File("./test.txt"));
builder.addPart("source", new StringBody("MyComputer",
ContentType.TEXT_PLAIN));
builder.addPart("folder_id", new StringBody("-1",
ContentType.TEXT_PLAIN));
builder.addPart("file_type", new StringBody("txt",
ContentType.TEXT_PLAIN));
builder.addPart("file_name", new StringBody("test.txt",
ContentType.TEXT_PLAIN));
builder.addPart("description", new StringBody("The file to test",
ContentType.TEXT_PLAIN));
builder.addPart("data", bin);
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
HttpResponse response = client.execute(httpPost);
String responseString = new BasicResponseHandler()
.handleResponse(response);
System.out.println(responseString);
my problem is in the server, i keep receive that the number of the parts is zero. for somewho the server is not receiving the parts (note i am not saying there is exceptions in the server)
I am saying this because on the server (my servlet) i do this
Iterator<Part> partsIterator = request.getParts().iterator();
System.out.println("The number of parts is :"
+ request.getParts().size());
and the result of the printing is always zero, always
what am i missing please?
Servlets' multipart configuration expects a Content-Type of multipart/form-data.
This is specified, among other places, in the javadoc of #MultipartConfig
Annotation that may be specified on a javax.servlet.Servlet class,
indicating that instances of the Servlet expect requests that conform
to the multipart/form-data MIME type.
You're specifying a different content type
httpPost.addHeader("Content-Type", "multipart/related; boundary=HereItGoes");
Get rid of this. The MultipartEntityBuilder already builds a request with the appropriate headers. Just add
builder.setBoundary("HereItGoes")
for the boundary.
Example Servlet
#WebServlet(loadOnStartup = 1, urlPatterns = "/multipart1")
#MultipartConfig()
public class MyServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("The number of parts is :" + request.getParts().size());
Iterator<Part> partsIterator = request.getParts().iterator();
while (partsIterator.hasNext()) {
System.out.println(partsIterator.next().getName());
}
}
}
It will receive all 6 of the parts you send with the code in your question.

How to pass a JSON string as a POST param avoiding character encoding in Java?

I'm trying to send a POST param to a REST endpoint I have. This param is a JSON String, that contains special chars like double quotes ("). On the endpoint I keep on getting the String encoded.
THis is the request part:
HttpClient client = HttpClientBuilder.create().build();
StringBuilder query = new StringBuilder();
query.append(callBackURL);
ArrayList<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("update", "{\"object\":\"page\",\"entry\":[{\"id\":\"316492991876763\",\"time\":1417436403,\"changes\":[{\"field\":\"feed\",\"value\":{\"item\":\"comment\",\"verb\":\"add\",\"comment_id\":\"321528008039928_323256911200371\",\"parent_id\":\"316492991876763_321528008039928\",\"sender_id\":100006737955082,\"created_time\":1417436403}}]}]}"));
try {
HttpPost post = new HttpPost(query.toString());
post.setEntity(new UrlEncodedFormEntity(urlParameters));
post.addHeader("content-type", "application/json");
HttpResponse response = null;
try {
response = client.execute(post);
}
catch (IOException e) {
System.out.println(e.getMessage());
}
}
catch (UnsupportedEncodingException e2) {
System.out.println(e2.getMessage());
}
Now in the endpoint part:
/**
* Callback method that receives FB updates
* #return 200 OK if everything goes OK, 401 ERROR otherwise
*/
#POST
#Path("/callback")
#Consumes(MediaType.APPLICATION_JSON)
public Response facebookUpdate(String update, #Context HttpServletRequest request, #Context HttpServletResponse response) throws ServletException, IOException{
JsonParser jsonParser = new JsonParser();
//parse it
JsonElement json = jsonParser.parse(update);
...
}
What I'm getting is a String encoded like this:
%7B%22object%22%3A%22page%22%2C%22entry%22%3A%5B%7B%22id%22%3A%22316492991876763%22%2C%22time%22%3A1417436403%2C%22changes%22%3A%5B%7B%22field%22%3A%22feed%22%2C%22value%22%3A%7B%22item%22%3A%22comment%22%2C%22verb%22%3A%22add%22%2C%22comment_id%22%3A%22321528008039928_323256911200371%22%2C%22parent_id%22%3A%22316492991876763_321528008039928%22%2C%22sender_id%22%3A100006737955082%2C%22created_time%22%3A1417436403%7D%7D%5D%7D%5D%7D
Something I cannot convert to a JsonElement...
Any ideas how to avoid this?
Thanks!
Alejandro
UPDATE:
I found what the problem was, so I'm explaining it here in case anyone has the same problem.
I was trying to pass a param using a BasicNameValuePair, like so:
ArrayList<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("update", "{\"object\":\"page\",\"entry\":[{\"id\":\"316492991876763\",\"time\":1417436403,\"changes\":[{\"field\":\"feed\",\"value\":{\"item\":\"comment\",\"verb\":\"add\",\"comment_id\":\"321528008039928_323256911200371\",\"parent_id\":\"316492991876763_321528008039928\",\"sender_id\":100006737955082,\"created_time\":1417436403}}]}]}"));
I've changed to a simple StringEntity, like this:
StringEntity params = new StringEntity(json.toString());
HttpPost post = new HttpPost(query.toString());
Thus, I don't need to decode. Mistery remains on why passing an Array of BasicNameValuePair will encode the String...
use annotation above the method you want to produce JSON from
#Produces("application/json")

http post method in struts2

when i try to execute this alfresco webscript [http://localhost:8383/alfresco/service/get-order-info] through Advance REST client (google chrome add-on) then it works smoothly but when i try to execute by following code then it gives error at this line JSONObject jsonObject = (JSONObject) new JSONParser().parse(responseString);
public class ComplainMasterDaoImpl implements ComplainMasterDao
{
#Override
public ComplainMaster fetchComplainInfo(String orderId, String user) throws Exception
{
// TODO Auto-generated method stub
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://localhost:8383/alfresco/service/get-order-info");
List<NameValuePair> formParams = new ArrayList<NameValuePair>();
formParams.add(new BasicNameValuePair("orderId", orderId));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formParams, "UTF-8");
httpPost.setEntity(formEntity);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
String responseString = IOUtils.toString(httpEntity.getContent(), "UTF-8");
JSONObject jsonObject = (JSONObject) new JSONParser().parse(responseString);
JSONObject resultJson = (JSONObject) jsonObject.get("result");
System.out.println(resultJson.toString());
return null;
}
}
and when i debugged it then i got resonseString like Apache Tomcat/6.0.29 - Error report HTTP Status 401 - type Status reportmessage description This request requires HTTP authentication ().Apache Tomcat/6.0.29
content of get-order-info.post.desc.xml :
<webscript>
<shortname>Get Order Information</shortname>
<description>Used to create complain</description>
<url>/get-order-info</url>
<format default="json"> </format>
<authentication>user</authentication>
</webscript>
Double check your description file. and check which level of authentication you want to provide while web script development.
In webscript desc.xml file, authentication (optional) is the required level of authentication; valid values are:
none: specifies that no authentication is required at all
guest: specifies that at least guest authentication is required
user: specifies that at least named user authentication is required
admin: specifies that at least a named admin authentication is required
Note: if not specified, the default value is none
Note: The optional runas attribute can be used to force the execution of a web script as a specific user. This can only be specified for web scripts that are stored in the Java Class path.
refer the following link for more details:
http://wiki.alfresco.com/wiki/Web_Scripts
Or else if you want to keep your web script for only authenticated users, then you need to pass required authentication details for the user who is accessing the web script from struts. But make sure that the user must exists in alfresco.
So, add following code in your fetchComplainInfo method for basic authentication:
String basic_auth = new String(Base64.encodeBase64((YOUR_USER_NAME+":"+YOUR_PASSWORD).getBytes()));
httpPost.addHeader("Authorization", "Basic " + basic_auth);
So, your method will be like this:
public class ComplainMasterDaoImpl implements ComplainMasterDao
{
#Override
public ComplainMaster fetchComplainInfo(String orderId, String user) throws Exception
{
// TODO Auto-generated method stub
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://localhost:8383/alfresco/service/get-order- info");
String basic_auth = new String(Base64.encodeBase64((YOUR_USER_NAME+":"+YOUR_PASSWORD).getBytes()));
httpPost.addHeader("Authorization", "Basic " + basic_auth);
List<NameValuePair> formParams = new ArrayList<NameValuePair>();
formParams.add(new BasicNameValuePair("orderId", orderId));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formParams, "UTF-8");
httpPost.setEntity(formEntity);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
String responseString = IOUtils.toString(httpEntity.getContent(), "UTF-8");
JSONObject jsonObject = (JSONObject) new JSONParser().parse(responseString);
JSONObject resultJson = (JSONObject) jsonObject.get("result");
System.out.println(resultJson.toString());
return null;
}
}
Well my guess is that you are authenticated in alfresco in another tab of google chrome and that alfresco picks that up. 401 is an authentication exception and you need to authenticate to alfresco which is not done in your code above. See for example:
http://wiki.alfresco.com/wiki/Web_Scripts#Authenticating
The first thing you should do is to check you webscripts description file to find out which authentication method it demands. Since this seems to be a custom webscript in you alfresco installation its hard to tell you where it is to be found. It could be called something like get-order.info.post.desc.xml (strange with a post request to a script named get- BTW) Look at the authentication element.

Submit an httpRequest method post to an apache server with java se

i'm trying to use a website from my java application as i'd do through my browser; it's the first time i'm trying something like this and i'm afraid i'm missing something.
I'm using apache httpcore libraries to do the http requests with the post method, with wireshark i've seen the parameters in the post request and i've added them to the request i do with java; the same for the headers.
If i sniff the request made with java i can't capture the http post request, but only the tcp traffic.
This is how i do the request:
HttpPost httpPost = new HttpPost("http://xxx.xxx");
httpPost.setHeader("Host", "xxx.xxx:xxxx");
.
.
.
HttpParams params = new BasicHttpParams();
params.setParameter("aaaa", "bbbb");
.
.
.
HttpResponse response = httpclient.execute(httpPost);
Am i missing something?
I should check something else?
Thank you very much for the help!
You have to supply a body with your post request, which you do so by calling the .setEntity(HttpEntity) method on your HttpPost.
private void sendToPostProxy(HttpServletRequest request,
HttpServletResponse response) throws IOException {
//the url to forward too
String url = "http://127.0.0.1:"+proxyPort+request.getRequestURI()
+(request.getQueryString()==null?"":"?"+request.getQueryString());
HttpPost get = new HttpPost(url);
//I am streaming requests straight through, but there are many Entity types you can use
get.setEntity(new InputStreamEntity(request.getInputStream(), request.getContentLength()));
sendToProxy(request, response, get);
}
private void sendToProxy(HttpServletRequest request,
HttpServletResponse response,HttpRequestBase get) throws IOException {
DefaultHttpClient client = new DefaultHttpClient();
Enumeration headers = request.getHeaderNames();
//copy headers
while(headers.hasMoreElements()){
String next = String.valueOf(headers.nextElement());
String header = request.getHeader(next);
if (!get.containsHeader(next)&&!"Content-Length".equalsIgnoreCase(next))
get.addHeader(next, header);
}
try{
//perform post
HttpResponse proxied = client.execute(get);
//set client headers
for (Header h : proxied.getAllHeaders()){
response.setHeader(h.getName(), h.getValue());
}
//stream to client
HttpEntity body = proxied.getEntity();
body.writeTo(response.getOutputStream());
response.setStatus(HttpServletResponse.SC_OK);
}catch(Exception e){
e.printStackTrace();
get.abort();
}
}

Proxy Servlet for HTTPS

I have a secure site that needs to display images coming from external non-https URLs on certain pages. I want to create a servlet that is used only as a proxy to pass the image data to the pages. One way is to use Apache's HttpClient to download the image data and then use IOUtils.copy to copy the data to the servlet's response.
Is there a simpler way?
UPDATE: The reason for this is to avoid browser warnings.
This is what I ended up using:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
String url = request.getParameter("url");
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
InputStream inputStream = httpEntity.getContent();
response.setContentType("image/jpeg");
IOUtils.copy(inputStream, response.getOutputStream());
} catch (Exception e) {
AppLogger.log(e);
}
}
If anyone has a better way to accomplish this, please post it.
If I understand well, you don't need anything like that, just return the references to the images or audio, or anything else in your HTML response and the browser will take care of make request to the server that contains each of the resources, if they're reachable, they will be displayed on the client.

Categories