I'm building a java server which have to handle http requests. I'm trying to handle a GET request and it works partially fine. In the specific case I want to discuss here I want to respond with a Json. This is what i'm doing:
private Socket socket;
OutputStream outputStream = socket.getOutputStream();
String json = gson.toJson(conversazione);
String response =
"HTTP/1.1 200 OK" + CRLF +
"Content-Length: " + (json.getBytes().length)+ CRLF +
"Content-Type: application/json;charset=UTF-8" + CRLF +
"Server: Federico's Java Server" + CRLF +
"Date: " + new Date() + CRLF + CRLF +
json + CRLF + CRLF;
outputStream.write(response.getBytes());
It works, i mean the client receive the status 200 OK but it receive a text instead of the Json. I'm doing a request with Postman and this is what it receive as response:
Are you sure CRLF = "\r\n"? It looks inverted.
"\n\r" might be interpreted as two lines (Unix+MacOS), hence the HTTP header ends after the first line.
Also better call .getBytes(StandardCharsets.UT8).
I think the issue you have is that you are sending the HTTP Headers and the body together, they need to be separate.
A found this article after a quick search which demonstrates this. From the code sample in that article (slightly adjusted to use the values in your sample):
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedOutputStream dataOut = new BufferedOutputStream(connect.getOutputStream());
String content = "application/json;charset=UTF-8";
byte[] fileData = json.getBytes();
int fileLength = (int) file.length();
// send HTTP Headers
out.println("HTTP/1.1 200 OK");
out.println("Server: Federico's Java Server");
out.println("Date: " + new Date());
out.println("Content-type: " + content);
out.println("Content-length: " + fileLength);
out.println(); // blank line between headers and content, very important !
out.flush(); // flush character output stream buffer
dataOut.write(fileData, 0, fileLength);
dataOut.flush();
I encourage to go check that article out. My sample above was written manually and my not work as expected.
Related
I'm trying to open a socket, send a message (requesting the HEAD) and get the response from server.
My code is similar to a lot of other codes I'm looking for, here in SO,or googling.
Here is:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
public class ClientTCPSocket {
public static final int PORT = 80;
public static void main(String argv[]) {
BufferedReader inputKeyboard = new BufferedReader(new InputStreamReader(System.in));
Socket socket;
InetAddress ipAddress;
String host = "";
String head = "";
String input_message = "";
try {
System.out.println("Host to connect?");
host = inputKeyboard.readLine();
head = "HEAD / HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n"
+ "\r";
ipAddress = InetAddress.getByName(host);
socket = new Socket(ipAddress, PORT);
DataOutputStream ouput = new DataOutputStream(socket.getOutputStream());
System.out.println("\nSending info...");
System.out.println(head);
System.out.println("===============================");
ouput.writeUTF(head);
BufferedReader inputFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((input_message = inputFromServer.readLine()) != null) {
System.out.println(input_message);
}
System.out.println("===============================");
socket.close();
inputFromServer.close();
} catch (IOException e) {
System.out.println("Alguna cosa ha anat malament");
e.printStackTrace();
}
}
}
(As I read in wiki: https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Message_format I need to put the carriage and line feed. I said that because I tested only using "\n")
But after all, If I call for example "localhost" (I got a basic xampp opened in the mac) or even "google.com", I'm getting Error 400, BAD Request, when is supposed I had to receive code 200.
I don't know what I'm forgetting or which combination of info I have to send .
Your problems are caused by multiple reasons:
Usage of writeUTF
From the documentation of ouput.writeUTF(head);
Writes a string to the underlying output stream using modified UTF-8 encoding in a machine-independent manner.
First, two bytes are written to the output stream as if by the writeShort method giving the number of bytes to follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each character of the string is output, in sequence, using the modified UTF-8 encoding for the character. If no exception is thrown, the counter written is incremented by the total number of bytes written to the output stream. This will be at least two plus the length of str, and at most two plus thrice the length of str.
Since these 2 bytes are prefixed to your string, it is causing an invalid HTTP request
You should manually convert your string to bytes, and send that, or use an InputStreamWriter
ouput.write(head.getBytes(StandardCharsets.UTF_8));
Missing trailing \n
Your final newline in the message is incomplete
head = "HEAD / HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n"
+ "\r";
should be
head = "HEAD / HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n"
+ "\r\n";
Assuming the end of the stream is reached
In HTTP 1.1, all connections are persistent by default, this means that the server will keep the connection open for a while after a request.
WHile you don't see the effect at the moment (because the malformed request, the server assumes its HTTP 1.0), this is a problem if you start sending valid requests.
Since this means that your program never breaks out of the for loop, we need to either detect the end of a request (hard!), or be a little less efficient and say to the server that we want to close our connection:
head = "HEAD / HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n"
+ "Connection: close\r\n"
+ "\r\n";
Missing user agent
While this isn't a violation of the protocol persee, some server may require the user agent header these days, and reject all connections without this header.
This is really easy.
head = "HEAD / HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n"
+ "user-agent: Test program made by https://stackoverflow.com/users/1282166/shudy\r\n"
+ "\r\n";
I'm a stranger to Java, but I'm developing an app with Processing, and I need enlightenment, please.
I'm running a php server on 127.0.0.1:8080 on the root of the .pde below. all my php scripts are bug free, as well as the rest of the Processing code.
after careful analysis, I've learned that the bug is in the function below.
what is the raised exception down under telling me? and how can I fix the code?
//(cont)
void postPicture(){
//load the saved image into an array of bytes
byte[] thisFile=loadBytes(fileName);
//open a new connection to the server
thisClient = new Client(this, "localhost", 80);
//make an HTTP POST request:
thisClient.write("POST " + pictureScriptUrl + " HTTP/1.1\n");
thisClient.write("Host: localhost\n");
//tell the server you're sending the POST in multiple parts
//and send a unique string that will delineate the parts
thisClient.write("Content-Type: multipart/form-data; boundary=");
thisClient.write(boundary + "\n");
//form the beginning of the request
String requestHead ="--" + boundary + "\n";
requestHead +="Content-Disposition: form-data; name=\"file\"; ";
requestHead += "filename=\"" + fileName + "\"\n";
requestHead +="Content-Type: image/jpeg\n\n";
//form the end of the request
String tail="\n\n--" + boundary + "--\n";
//calculate and send the length of the total request
//including the head of the request, the file, and the tail
int contentLength = requestHead.length() + thisFile.length + tail.length();
thisClient.write("Content-Length: " + contentLength + "\n\n");
//send the header of the request, the file and the tail
thisClient.write(requestHead);
thisClient.write(thisFile);
thisClient.write(tail);
}
java.lang.NullPointerException
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at javax.imageio.stream.FileCacheImageOutputStream.close(FileCacheImageOutputStream.java:238)
at com.sun.imageio.stream.StreamCloser$CloseAction.performAction(StreamCloser.java:130)
at com.sun.imageio.stream.StreamCloser$1.run(StreamCloser.java:74)
at java.lang.Thread.run(Thread.java:745)
I'm trying to send a request through Google's Safe Browsing API, but I'm not getting any output and I'm not sure why. I've searched this online but each solution either only refers to only how to send or receive a POST request (but not both), or the input of data is done differently.
According to the Google Safe Browsing documentation:
Specify the queried URLs in the POST request body using the following format:
POST_REQ_BODY = NUM LF URL (LF URL)*
NUM = (DIGIT)+
URL = URL string following the RFC 1738
-
Response body:
POST_RESP_BODY = VERDICT (LF VERDICT)*
VERDICT = “phishing” | “malware” | "unwanted" | “phishing,malware” >| "phishing,unwanted" | "malware,unwanted" | "phishing, malware, unwanted" >| “ok”
and sent to:
https://sb-ssl.google.com/safebrowsing/api/lookup?client=CLIENT&key=APIKEY
I found another topic that shows how you send this request, but I'm not sure how to get/print out the response. Here is what I tried:
String baseURL="https://sb-ssl.google.com/safebrowsing/api/lookup";
String arguments = "";
arguments +=URLEncoder.encode("client", "UTF-8") + "=" + URLEncoder.encode("myapp", "UTF-8") + "&";
arguments +=URLEncoder.encode("apikey", "UTF-8") + "=" + URLEncoder.encode("12345", "UTF-8") + "&";
arguments +=URLEncoder.encode("appver", "UTF-8") + "=" + URLEncoder.encode("1.5.2", "UTF-8") + "&";
arguments +=URLEncoder.encode("pver", "UTF-8") + "=" + URLEncoder.encode("3.0", "UTF-8");
// Construct the url object representing cgi script
URL url = new URL(baseURL + "?" + arguments);
// Get a URLConnection object, to write to POST method
URLConnection connect = url.openConnection();
// Specify connection settings
connect.setDoInput(true);
connect.setDoOutput(true);
InputStream input = connect.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
// Get an output stream for writing
OutputStream output = connect.getOutputStream();
PrintStream pout = new PrintStream (output);
pout.print("2");
pout.println();
pout.print("http://www.google.com");
pout.println();
pout.print("http://www.facebook.com");
pout.close();
while((line = reader.readLine()) != null) {
result.append(line);
}
System.out.println(result.toString());
Where is the error?
Move these lines:
InputStream input = connect.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
After pout.close();, the getInputStream method actually send the HTTP request to the server, in that example you are sending the request before you fill the body.
It looks like there will be other things to fix after this.
When trying to void a in-progress document, I received the invalid_request_body error(The request body is missing or improperly formatted. Data at the root level is invalid). Is there something missing on the request body ?
url = baseURL + "/envelopes/" + envelopeId;
body = "";
// re-use connection object for second request...
conn = InitializeRequest(url, "PUT", body, authenticationHeader);
String requestBody = "\r\n\r\n--BOUNDARY\r\n" +
"Accept: application/xml" +
"Content-Type: application/xml\r\n" +
"\r\n" +
body + "\r\n\r\n--BOUNDARY\r\n" +
"status: voided\r\n" +
"voidedReason: Time-out\r\n" +
"\r\n";
String reqBody2 = "\r\n" + "--BOUNDARY--\r\n\r\n";
DataOutputStream dos= new DataOutputStream( conn.getOutputStream() );
dos.writeBytes(requestBody.toString());
//dos.write(bytes);
dos.writeBytes(reqBody2.toString());
dos.flush();
dos.close();
System.out.println("STEP 2: Retrieving envelope information for envelope " + envelopeId + ".\n");
status = conn.getResponseCode(); // triggers the request
if( status != 200 ) { // 200 = OK
System.out.println(conn);
System.out.println(status);
errorParse(conn, status);
throw new RuntimeException();
}
// display results
response = getResponseBody(conn);
Following up with your comments for the benefit of the community...
This is the request body that worked for you in the end:
request body## String requestBody = "<envelope>" + "<status>voided</status>" + "<voidedReason>user aborted</voidedReason>" + "</envelope>"
I asked a similar question in another thread but I think I'm just having trouble getting the syntax right at this point. I basically want to open a socket in Java, send a HTTP request message to get the header fields of a specific web page. My program looks like this so far:
String server = "www.w3.org";
int port = 80;
String uri = "/Protocols/rfc2616/rfc2616-sec5.html#sec5.1"
Socket socket = new Socket(server, port);
PrintStream output = new PrintStream(socket.getOutputStream());
BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output.println("HEAD " + uri + " HTTP/1.1");
//String response = "";
String line = "";
while((line = socketInput.readLine()) != null){
System.out.println(line);
}
socketInput.close();
socket.close();
It doesn't really work. Or it doesn't work for all websites. If someone could just tell me the immediate problems with what I'm doing, that would be great. Thank you!
Change
output.println("HEAD " + uri + " HTTP/1.1");
to
output.println("HEAD " + uri + " HTTP/1.1");
output.println("Host: " + server);
output.println();
You have to send the Host header because usually there are more than one virtual host on one IP address. If you use HTTP/1.0 it works without the Host header.
I would use some higher-level component, like HttpURLConnection (see here) or apache http components.