The following method sends a JSON reply. However on the receiving end I keep getting invalid characters, and UTF-8 isn't decoding the data. What am I doing wrong?
Response to client = data output stream
//Get the client request
clientRequest = new BufferedReader(new InputStreamReader(connectedClient.getInputStream())); //connectedclient = socket
//Start response object
responseToClient = new DataOutputStream(connectedClient.getOutputStream());
/**
* Sends a JSON response for an object
* #param objectToEncode
* #throws Exception
*/
private void sendJSONResponse(Object objectToEncode) throws Exception{
//Encode object into JSON
String jsonString = new Gson().toJson(objectToEncode);
// HTTP Header... Status code, last modified
responseToClient.writeBytes(HTTP_OK_STATUS_CODE);
responseToClient.writeBytes(CONTENT_TYPE_JSON);
responseToClient.writeBytes("Last-modified: "+ HelperMethods.now() +" \r\n");
responseToClient.writeBytes("\r\n");
// The HTTP content starts here
responseToClient.writeBytes(jsonString);
}
I have no idea why you would write your own HTTP protocol code. It's a lot like writing your own XML parser: No matter how good a programmer you are, you are bound to get it wrong.
Anyway, as the DataOutputStream documentation states, doing writeBytes on a String will just discard its high eight bits. So what you get is... something, but not UTF8. What you should do is:
String jsonString = new Gson().toJson(objectToEncode);
byte[] utf8JsonString = jsonString.getBytes("UTF8");
responseToClient.write(utf8JsonString, 0, utf8JsonString.Length);
The first solution didn't work for me, I did this:
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
String json = gson.toJson(objectToEncode);
Use the following code to encode
response.setCharacterEncoding("UTF8"); // this line solves the problem
response.setContentType("application/json");
Related
I'm trying to send a Json format in body of POST request in java.
I tried a lot of codes from the internet and StackOverflow, but nothing is working.
I keep getting java.io.IOException: Server returned HTTP response code: 400 for URL: http://localhost:8080/engine-rest/message.
After trying a lot on Postman i noticed it only accepts Json format body, i tried using json libraries like Gson, yet still nothing worked.
Any ideas on how to fix my code? Again I did try to copy a lot of codes from the internet so please don't send me a similar title stackoverflow thread and call the question repetitive.
Thank you in advance.
public class PostRequest {
FileWriter myWriter;
URL url;
public void sendPost(String Url) throws IOException {
String name = "{\"messageName\": \"URLFound\", \"businessKey\": \"3\"}";
try {
myWriter = new FileWriter("C:\\Users\\test\\Desktop\\camunda test save\\Post.txt");
url = new URL ("http://localhost:8080/engine-rest" + Url);
HttpURLConnection http = (HttpURLConnection)url.openConnection();
http.setRequestMethod("POST");
http.setDoOutput(true);
http.setRequestProperty("Content-Type", "application/json");
OutputStream os = http.getOutputStream();
byte[] input = name.getBytes("utf-8");
os.write(input, 0, input.length);
BufferedReader in = new BufferedReader(new InputStreamReader(http.getInputStream()));
StringBuffer response = new StringBuffer();
while ((in.ready())) {
response.append(in.readLine());
}
in.close();
//Writing result on .txt
myWriter.append(response.toString() + "\n" +url);
}
catch(Exception e){
myWriter.append(e.toString());
}
myWriter.close();
}
}
How about using this client project?
https://github.com/camunda-community-hub/camunda-rest-client-spring-boot/
For example:
https://github.com/camunda-community-hub/camunda-rest-client-spring-boot/blob/dce6bd777e3350dd30286311c5351aa9460a34f4/examples/example/src/main/java/org/camunda/bpm/extension/rest/example/standalone/client/ProcessClient.java#L98
Java cant create an object from your json. Check if all fields are sent in the request body of the java class that is expected on the backend side.
I'm facing an issue with handling POST request using Java 11 embedded library java.net.
Client side:
I have two methods in my QueryGenerator class:
public String postTeachers(String newTeachersList) {
this.customRequest = HttpRequest.newBuilder()
.uri(URI.create("http://" + serverIPport + "/" + postTeachers))
.POST(HttpRequest.BodyPublishers.ofString(newTeachersList))
.build();
return getResponseResults();
}
It is used to create a post request.
And also I have a getResponseResults() method
private String getResponseResults() {
String result = null;
try {
CompletableFuture<HttpResponse<String>> response = CustomHttpClientSingleton.getInstance().sendAsync(customRequest, HttpResponse.BodyHandlers.ofString());
result = response.thenApply(HttpResponse::body).join();
} catch(RuntimeException e) {
System.out.println("Seems like the server may not be working properly! Restart it");
}
return result;
}
Server side:
I have a method handlePostRequest
private void handlePostRequest(HttpExchange httpExchange) throws IOException {
Headers headers = httpExchange.getResponseHeaders();
httpExchange.sendResponseHeaders(200, 0);
InputStream is = httpExchange.getRequestBody();
System.out.println(is.toString());
is.close();
}
I get the POST Request in my HttpServer, but when I try to display the contents of a request body, I don't get any information. I'm expecting to receive JSON representation of my ArrayList collection, but the only output I get is:
sun.net.httpserver.FixedLengthInputStream
Is there any way to get request body sent by http client inside POST request and use it on the server side by means of Java 11 java.net embedded library.
Thanks to everyone!
You must read Inputstream content, not just apply toString().
See https://www.baeldung.com/convert-input-stream-to-string
It looks like you are not reading input stream properly. Try to read input stream instead of calling toString() on it. Please check How to get an HTTP POST request body as a Java String at the server side?
for more information.
My issue is that the escape character is invalidating my JSON. I am sending my JSON to a Rails sever but when it arrives it gains some escape characters.
Is there something I can do to Solve this on my restfull class or is it something to be corrected on the server side?
Here is the JSON I'm sending,
[session={"password":"********","email":"********#omobile.com.br"}]
And here is the JSON thats appearing on the servers log:
{"session"=>"{\"password\":\"********\",\"email\":\"********#omobile.com.br\"}"}
I've tried these different ways to send my JSON and the result is the same:
JSONObject object = new JSONObject();
object.accumulate("email", username);
object.accumulate("password", password);
String jsonString = object.toString();
Session session = new Session();
session.setEmail(username);
session.setPassword(password);
Gson gson = new Gson();
String jsonString = gson.toJson(session, Session.class);
What happens is a mess, because neither of the strings you posted is actually JSON. The first one actually I don't know what it is, while the second one likely means that on the Ruby side you have this Ruby hash, in which the key "session" refers to a JSON-encoded hash.
We can't tell what's going on the wire because you didn't post the code, so we can't tell if your server expects a form-encoded request body, a multipart one, or directly a JSON-encoded object.
I want you to consider that the only JSON I see is the portion:
{"password": "********","email":"********#omobile.com.br"}
As I said, this can be passed as-is, or as a part in a mulipart envelope, or even url-encoded. The format is really estabilished on the server. For example I made a quick test using Apache HttpClient:
public class GsonSendToSinatra {
private static class Session {
#SuppressWarnings("unused")
String username, password;
}
public static void main(String[] args) throws Exception {
Session session = new Session();
session.username = "foo#example.com";
session.password = "qwerty1234";
Gson gson = new Gson();
String responseText = Request.Post("http://localhost:4567/echo")
.bodyString(gson.toJson(session), ContentType.APPLICATION_JSON)
.execute()
.returnContent()
.asString();
System.out.println(responseText);
}
}
and Sinatra on the server:
require 'sinatra'
require 'json'
post '/echo' do
content_type "text/plain"
layout false
session = JSON.parse request.body.read
session.map {|k,v| "#{k}: #{v}\n"}
end
I hope this example helps you to figure out what are the moving parts in a HTTP dialogue and how you can combine them.
I'm trying to make a webservice call where I have to pass
login.php?message=[{"email":"mikeymike#mouse.com","password":"tiger"}]
I've use backslash to escape the double quotes like this
String weblink = "login.php?message=[{\"email\":\"mikeymike#mouse.com\",\"password\":\"tiger\"}]";
But I'm still getting errors. I've tried making calls to other webservices which don't have require data with any double quotes and they work fine so I'm quite sure the problem is from this. Also I get a java.lang Exception saying
java.lang.Exception Indicates a serious configuration error.DateParseException An exception to indicate an error parsing a date string. DestroyFailedException Signals that the destroy() method failed
EDIT:
I've tried using URLEncoder and JSON object but still get an error
Here is the rest of the code
String HOST = "http://62.285.107.329/disaster/webservices/";
String weblink = "login.php?message=[{\"email\":\"mikeymike#mouse.com\",\"password\":\"tiger\"}]";
String result = callWebservice(weblink);
public String callWebservice(String weblink) {
String result = "";
try {
HttpParams httpParameters = new BasicHttpParams();
int timeoutConnection = 7500;
HttpConnectionParams.setConnectionTimeout(httpParameters,
timeoutConnection);
int timeoutSocket = 7500;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpClient client = new DefaultHttpClient(httpParameters);
HttpGet request = new HttpGet();
URI link = new URI(HOST + weblink);
request.setURI(link);
HttpResponse response = client.execute(request);
BufferedReader rd = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
result = rd.readLine();
} catch (Exception e1) {
e1.printStackTrace();
result = "timeout";
}
return result;
}
Also the webservice returns a JSON object so could this also be a reason for the error?
Instead of trying this by hand and getting errors, why don't use use a combination of the JSONObject class and UrlEncoder.
JSONObject json = new JSONObject();
json.put("email","mikeymike#mouse.com" );
json.put("password", "tiger");
String s = "login.php?message=" + UrlEncoder.encode(json.toString());
You have to use %22 in place of " as in: login.php?message=[{%22email%22:%22mikeymike#mouse.com%22,%22password%22:%22tiger%22}]
" is not a valid character in an URL.
A more general solution is to use URLEncoder.encode("login.php?message=[{\"email\":\"mikeymike#mouse.com\",\"password\":\"tiger\"}]", "UTF8")
When you communicate with web services you need to URL encode your data. In your case, the url encoding would replace " with %22, but if you were to add other special characters, such as %, the encoding would capture these as well. There is a java class in the JDK for this, called URLEncoder.
So, basically, what you would do is to prepare your string using URLEncoder.encode(), like so:
String weblink = URLEncoder.encode("login.php?message=[{\"email\":\"mikeymike#mouse.com\",\"password\":\"tiger\"}]");
Now that the string is encoded, you should be able to send it along to the server and have it understand what you mean.
Apologies to all but it seems the problem was that I was trying to consume the webservice in the wrong way as it returns a JSON object.
The proper way to do this for anyone who might come across this is in the code below
String str="url";
try{
URL url=new URL(str);
URLConnection urlc=url.openConnection();
BufferedReader bfr=new BufferedReader(new InputStreamReader(urlc.getInputStream()));
String line;
while((line=bfr.readLine())!=null)
{
JSONArray jsa=new JSONArray(line);
for(int i=0;i<jsa.length();i++)
{
JSONObject jo=(JSONObject)jsa.get(i);
title=jo.getString("deal_title"); //tag name "deal_title",will return value that we save in title string
des=jo.getString("deal_description");
}
}
catch(Exeption e){
}
This answer was gotten from
How to call a json webservice through android
Looking for a bit of help, I have currently written a HTTP server. It currently handles GET requests fine. However, whilst using POST the buffered reader seems to hang. When the request is stopped the rest of the input stream is read via the buffered reader. I have found a few things on google. I have tried changing the CRLF and the protocol version from 1.1 to 1.0 (browsers automatically make requests as 1.1) Any ideas or help would be appreciated. Thanks
I agree with Hans that you should use a standard and well-tested library to do this. However, if you are writing a server to learn about HTTP, here's some info on doing what you want to do.
You really can't use a BufferedReader because it buffers the input and might read too many bytes from the socket. That's why your code is hanging, the BufferedReader is trying to read more bytes than are available on the socket (since the POST data doesn't have an end of line), and it is waiting for more bytes (which will never be available).
The process to simply parse a POST request is to use the InputStream directly
For each line in the header
read a byte at a time until you get a '\r' and then a '\n'
Look for a line that starts with "Content-Length: ", extract the number at the end of that line.
When you get a header line that is empty, you're done with headers.
Now read exactly the # of bytes that came from the Content-Length header.
Now you can write your response.
Wouldn't write my own implementation. Look at the following existing components, if you want:
a HTTP client: Apache HttpClient
a HTTP server implementation: Apache HttpComponents core (as mentioned by Bombe)
This is not safe! But shows how to get the POST data during an Input Stream after the initial HTTP Headers.
This also only works for POST data coming in as "example=true&bad=false" etc.
private HashMap hashMap = new HashMap();
private StringBuffer buff = new StringBuffer();
private int c = 0;
private String[] post; public PostInputStream(InputStream in) {
try {
//Initalizes avaliable buff
if (in.available() != 0) {
this.buff.appendCodePoint((this.c = in.read()));
while (0 != in.available()) {
//Console.output(buff.toString());
buff.appendCodePoint((this.c = in.read()));
}
this.post = buff.toString().split("&");
for (int i = 0; i < this.post.length; i++) {
String[] n = this.post[i].split("=");
if (n.length == 2) {
hashMap.put(URLDecoder.decode(n[0], "UTF-8"), URLDecoder.decode(n[1], "UTF-8"));
} else {
Console.error("Malformed Post Request.");
}
}
} else {
Console.error("No POST Data");
}
} catch (Exception e) {
e.printStackTrace();
}
}
As karoroberts said you have to check the length of the content sent in the POST. But you still can use BufferedReader.
Just have to check for the Content-Length header for the size of it and after finishing reading all the headers you can set a char array of that size and make the reading of the POST content:
char[] buffer = new char[contentLength];
request.read(buffer);
Where request is the BufferedReader.
If you need the POST content in a string, you can use: String.valueOf(buffer);
Note: BufferedReader.read returns an int of the characters readed, so you could check there for inconsistencies with the Content-Length header.