Creation of HTTP server - java

I am learning Java and was given a task to implement a simplistic version of HTTP server that is able to:
accept /GET requests and route them based on the uri
accept /POST requests and route them based on the uri
respond with a proper HttpResponse
Here is where I am so far:
ServerSocket server = new ServerSocket(7777);
Socket socket = server.accept();
String httpResponse = "Http/1.1 200/OK\r\n\r\n " + new Date();
socket.getOutputStream().write(httpResponse.getBytes("UTF-8"));
and I am stuck. I understand how to return a "Hello World" HTTP response to everything, but I have no idea how to deal with HTTP requests.
Could you give me a possible direction or a couple of next steps I can take to move forward?

If you're looking for a basic example of an HTTP request you could use a tool like Postman (Google Chrome extension) or HttpRequester (Firefox extension) which allows you to construct requests and view the code.
For example here is a basic request:
GET /news/headlines?hl=en HTTP/1.1
Host: news.google.com
Cache-Control: no-cache
This request gets the Google News headlines page.
If you're looking for how to use sockets you could start with the Java Lesson: All About Sockets

Related

407 Proxy Authentication error - Unirest Java 8

Hi everyone i'm so hopeless so ask you guys.
I'm trying to do a simple HTTP request but with my proxies I get 407 error code.
I use Unirest and Java 8.
Unirest.config().proxy(host, port, usernameProxy, passwordProxy);
HttpResponse<JsonNode> response = Unirest.post(url).asJson();
String body = response.getBody().toString();
That's it, my url is private but i wrote it like this: "https://myurl.com/?param1=param&param2....
It works proxyless but i'm stuck with proxies.
Thanks a lot
Seems like the proxy server expects for the proxy credentials within the Headers, which Unirest doesn't seem to propagate.
The header must specifically contain the "Proxy-Authorization" key in order to the handshake be even started.
String proxyCred= "user:password";
String baseCred= Base64.getEncoder().encodeToString(proxyCred.getBytes());
HttpHeaders headers = new HttpHeaders();
headers.add("Proxy-Authorization", "Basic " + baseCred); // the proxy server needs this
This solution uses the Basic mechanism; It may not work, as the proxy may expect another type of authentication. You'll know which one is by reading the Proxy-Authenticate header within the server's response.
If the communication is not secured (HTTP and not HTTPS), you could read the response by sniffing the packet with some tool such as WireShark. Once you locate the 407 packet, you could read inside the Proxy-Authenticate value and modify your authorization method according do it.

Java Server Side: send Http POST response - status only

Some third party is sending an Http Post request whenever something changes in their DB (e.g. when a contact has been updated, they send the contactID and 'contact_updated'). I have build a socket listener that catches those requests and is able to parse the information. However, I just can't get it to work to send back a response with the status '200 - OK'. Thus, the server on the client side keeps on trying (four times or so) to re-send the request.
Is there any, simple way to just send the response status without the need of adding external libs etc.?
It should be enough to send the string HTTP/1.1 200 OK back in your socket-listener.
If you have troubles, you can check out this answer, it shows how to use a HttpServer in Java just via plain JavaSE features.
Use
response.setStatus(HttpServletResponse.SC_OK);
to set the status code in your response header.
You may also set the content type.
response.setContentType("text/html;charset=UTF-8");

IoT module GET request in Java

I'm trying to read a JSON response from a RESTful webserver running on an IoT module (Advantech WISE-4012). According to the documentation, any GET request should be made in this form
GET /ai_value/slot_0/ch_0
Any Java implementation of GET requests (Java libraries, Apache etc.), anyway, append to the end of the request the protocol signature HTTP/1.1. E.g:
GET http://192.168.0.14/ai_value/slot_0/ch_0 HTTP/1.1
Because of this (probably) i'm getting Error 400 (Bad request) on every client i tried so far. The only working method i've discovered was sending a simple request through the address bar on Google Chrome browser (sometimes i get a response, sometimes a get a bad request error either). How can i write a java implementation of a GET request plain and simple as described by the documentation? How can i test a custom GET request without HTTP/1.1 at the end? Every chrome extension i tried (Advanced REST Client, Postman) add the protocol version at the end, so i haven't had the chance to verify if that's why i'm getting a bad request error.
EDIT:
This is the response header from Advanced REST client
Connection: close
Content-Type: application/json
Server: WISE-4000/8.1.0020
While the source message is the following one:
GET /ai_value/slot_0/ch_0 HTTP/1.1
HOST: 192.168.0.14
The only mismatch between the documentation is the HTTP/1.1 signature as mentioned before. Adding the "accept: application/json" makes no difference either
After a bit of digging into the documentation, it looks like the default timeout (i.e. 720 seconds) is the one causing an issue. There doesn't seem to be any way to work it around (ideally, the system should reset the time after a successful request and we should only get 400 - or 403 ideally after 720 seconds of inactivity).
A couple of points I would like to recommend to the API developers for WISE-4012 (if they are in touch with you):
Add brief documentation for authentication and timeout (probably, more response codes and error messages with each error response)
Enable OAuth for API Access
As far as current implentation is conerned, I guess you need to do a basic auth and pass username/password with every request, Or add Authentication header with every API request to get successful response without any 400s.
Check if this helps.
HttpClient httpClient = HttpClients.createDefault();
URI reqUri = new URI(<uri>);
RequestBuilder requestBuilder = RequestBuilder.create("GET");
requestBuilder.setUri(reqUri);
requestBuilder.setHeader(<headerKey>, <headerValue>);
requestBuilder.setEntity(<entity_data>);
HttpUriRequest httpRequest = requestBuilder.build();
httpResponse = httpClient.execute(httpRequest);

Java: wait to receive a value from another server (by http?)

I am developing a web application with struts2&spring3 and one of the last things I need to do is the communication between my server and another server where I have to send a XML file and after wait for its response.
As someone said me, I have implemented the sending of the XML file by HTTP with the library HttpClient4 (from Apache):
File file = new File(fileName);
FileEntity entity = new FileEntity(file, "text/xml; charset=\"UTF-8\"");
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost method = new HttpPost(server);
method.setEntity(entity);
HttpResponse response = httpclient.execute(method);
But now I have to implement the waiting and getting of the response that the other server will send me. The problem is that the other server is still not developed, so, which way you think it would be the best to get that answer? by HTTP also would be perfect but I don't know which library and how to do it.
Thank you very much in advance for all your help,
Aleix
Here I find two options
Send response immediately.
Develop a module [client side] which accepts response from server after request is received and added to queue [ Asynchronous mode ]

Is Jakarta HttpClient sutitable for the following task?

I try to talk to a server, by telneting to it, and send the following command through telnet terminal :
POST /%5bvUpJYKw4QvGRMBmhATUxRwv4JrU9aDnwNEuangVyy6OuHxi2YiY=%5dImage? HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 164
[SORT]=0,1,0,10,5,0,KL,0&[FIELD]=33,38,51,58,68,88,78,98,99,101,56,57,69,70,71,72,89,90,91,92,59,60,61,62,79,80,81,82&[LIST]=1155.KL,1295.KL,7191.KL,0097.KL,2267.KL
This works very fine. Now, I wish I can use HttpClient, to talk to the server, as I use telnet to talk to the server. The reason I wish to use HttpClient, instead of using raw TCP socket, is because HttpClient does support NTLM.
However, when I use POST method with NameValuePair :
new NameValuePair("[SORT]", "0,1,0,10,5,0,KL,0")
The request will become URL encoded. The server doesn't understand URL encoded request.
%5BSORT%5D: 0%2C1%2C0%2C10%2C5%2C0%2CKL%2C0
Is there any way I can avoid this? If not, what is the alternative library I can use? I wish to support NTLM as well.
As I mentioned in the other thread, this is not even valid HTTP POST. So you can't do it with default post mechanism in HttpClient. You need to make the invalid body yourself and post it.
Assuming you are using HttpClient 3, following code should work,
HttpClient httpClient = new HttpClient();
PostMethod method = new PostMethod(url);
String badFormPost = "[SORT]=0,1,0,10,5,0,KL,0&[FIELD]=33,38,51,58,68,88,78,98,99,101,56,57,69,70,71,72,89,90,91,92,59,60,61,62,79,80,81,82&[LIST]=1155.KL,1295.KL,7191.KL,0097.KL,2267.KL";
RequestEntity entity = new StringRequestEntity(badFormPost,
"application/x-www-form-urlencoded", "UTF-8");
method.setRequestEntity(entity);
method.setContentChunked(false);
httpClient.executeMethod(method);
...
It's getting URL encoded because your request formed with HTTPClient may be a GET request instead of a POST and is missing this header:
Content-Type: application/x-www-form-urlencoded
Look for the HTTPClient setting to set the Content-Type header correctly and make sure your request is a POST, not a get and you should be golden.

Categories