I have simple http server on android from Android Samples. I like this server, so I also want to recive POST data from browser. How can I recive it with standart things (without external libraries) ? I try to recive it like GET, but js console show connection error.
private void handle(Socket socket) throws IOException {
BufferedReader reader = null;
PrintStream output = null;
try {
String route = null;
// Read HTTP headers and parse out the route.
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while (!TextUtils.isEmpty(line = reader.readLine())) {
if (line.startsWith("GET /")) {
int start = line.indexOf('/') + 1;
int end = line.indexOf(' ', start);
route = line.substring(start, end);
break;
}
}
// Output stream that we send the response to
output = new PrintStream(socket.getOutputStream());
// Prepare the content to send.
if (null == route) {
writeServerError(output);
return;
}
byte[] bytes = loadContent(route);
if (null == bytes) {
writeServerError(output);
return;
}
// Send out the content.
output.println("HTTP/1.0 200 OK");
output.println("Content-Type: " + detectMimeType(route));
output.println("Content-Length: " + bytes.length);
output.println();
output.write(bytes);
output.flush();
} finally {
if (null != output) {
output.close();
}
if (null != reader) {
reader.close();
}
}
}
full code
In general the http request is a text fragment. The type of the request is indicated in the text. So in a GET request the example you provide first finds the "GET" string. Then parses the get request. The same should be done for POST. First identify the "POST" then parse the rest of the request.
Related
I want to get an image from a server by making http request manually . I make a connection , create a http request wait for , get the http reply from server and then i want data inside it.I separated header from data and saved it into a file with ".jpeg" extension . But my .jpeg file could not be opened. What can i do ?
Note: i cant use any plugin or libraries . I just can process on http request!
Here my code :
try (Socket socket = new Socket("ceit.aut.ac.ir", 80)) {
// send an HTTP request to the web server
DataOutputStream outToServer = new DataOutputStream(socket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
outToServer.writeBytes("GET /~94131090/CN1_Project_Files/flower.jpeg HTTP/1.1\r\n");
outToServer.writeBytes("Host: ceit.aut.ac.ir:80\r\n");
outToServer.writeBytes("Connection: Close\r\n");
outToServer.writeBytes("Content-Type:image/*\r\n");
outToServer.writeBytes("\r\n");
// Receive an HTTP reply from the web server
boolean loop = true;
StringBuilder sb = new StringBuilder();
while (loop) {
if (inFromServer.ready()) {
int i = 0;
while (i != -1) {
i = inFromServer.read();
sb.append((char) i);
}
loop = false;
}
}
//Download Image
String data = separate(sb.toString());
//???
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
Here my separate function :
public String separate(String str){
String msg = str;
int index = msg.indexOf("close");
// "close" and blank end of http response line including \r\n
// 3(close) + 2(\r) + 2 (\n) + 2 (\r) + 2 (\n) = 4 + 2 + 2 + 2 = 6
return msg.substring(index+11);
}
We would like to create a simple JAVA proxy server that would gather info from the request headers if need be.
We have implemented the proxy server, pointed our browser to the host and port, and we are able to browse sites that use simple HTTP protocol without an issue.
We support the GET and HEAD HTTP methods.
However, sites that use HTTPS cause an issue, as these initiate a CONNECT method, and we can't get the secure connection up, we are not sure what to send in the response. (Or if we would be able to monitor further requests from that point onward.)
Any suggestions? Any 3rd party implementation would do. But we would like to support HTTP and HTTPS in the same process.
private void intercept() throws IOException {
final DataInputStream socketInput = new DataInputStream(this.socket.getInputStream());
final String httpMessage = RequestHeader.readHttpHeader(socketInput);
//Request header is our own convenience file with utility methods that parses the request header.
requestHeader = new RequestHeader(httpMessage);
try {
if ("GET".equals(requestHeader.getType()) || "HEAD".equals(requestHeader.getType())) {
final URL url = new URL(requestHeader.getUrl());
final HttpURLConnection connectionHttp = (HttpURLConnection) url.openConnection();
connectionHttp.setRequestMethod(requestHeader.getType());
// Send response back to client
final DataInputStream dis = new DataInputStream(connectionHttp.getInputStream());
// Add response header
final StringBuilder sb = new StringBuilder();
sb.append(requestHeader.getHttpVersion() + " " + connectionHttp.getResponseCode() + " "
+ connectionHttp.getResponseMessage() + "\r\n");
final Map<String, List<String>> map = connectionHttp.getHeaderFields();
for (final Map.Entry<String, List<String>> entry : map.entrySet()) {
final String key = entry.getKey();
sb.append(key + " : "
+ entry.getValue().toString().replace("[", "").replace("]", "").replace(",", " ") + "\r\n");
}
sb.append("\r\n");
// Add response content
final DataOutputStream socketOutput = new DataOutputStream(this.socket.getOutputStream());
socketOutput.write(sb.toString().getBytes(), 0, sb.toString().getBytes().length);
final byte[] data = new byte[(int) Short.MAX_VALUE];
int index = dis.read(data, 0, (int) Short.MAX_VALUE);
while (index != -1) {
socketOutput.write(data, 0, index);
index = dis.read(data, 0, (int) Short.MAX_VALUE);
}
socketOutput.flush();
// NOTE this works perfectly fine for HTTP sites. We can intercept the communication properly.
} else if ("CONNECT".equals(requestHeader.getType())) {
// TODO establish connection
// First line of header: CONNECT www.facebook.com:443 HTTP/1.1
// We have tried to send back 200 ok response, but no further requests were sent.
} else {
//Nothing else is supported
return;
}
} catch (final MalformedURLException e) {
System.out.print("MalformedURLException " + e.getMessage());
// return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (final IOException e) {
System.out.print("IOException " + e.getMessage());
// return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
} finally {
System.out.println("Finished.");
}
}
HTTPComponents supports HTTPS. Also, you don't have to write the socket logic yourself, so there's that.
If I recall right, HTTPS works out of the box, no need for any odd configuration or special ssl calls.
I am trying to write a program in java which is able to download a file from a URL. I want to do this without using an URLConnection, instead i am just using TCP sockets. I have succeeded in sending the GET request and picking up the server's response, but i can't seem to get my head around saving the file from the response without the http-header(just the file).
import java.net.*;
import java.io.*;
public class DownloadClient {
public static void main(String[] args) {
try {
if (args.length != 3) {
System.out.println(
"Use: java DownloadClient <host> <port> <filename/path>"
);
} else {
// Sorting out arguments from the args array
String host;
int port;
String filename;
if (args[0].charAt(args[0].length()-1) == '/') {
host = args[0].substring(0,args[0].length()-1);
} else {
host = args[0];
}
port = Integer.parseInt(args[1]);
if (args[2].charAt(0) == '/') {
filename = args[2];
} else {
filename = "/"+args[2];
}
Socket con = new Socket(args[0], Integer.parseInt(args[1]));
// GET request
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(con.getOutputStream(), "UTF8")
);
out.write("GET "+filename+" HTTP/1.1\r\n");
out.write("Host: "+host+"\r\n");
out.write("User-Agent: Java DownloadClient\r\n\r\n");
out.flush();
InputStream in = con.getInputStream();
BufferedReader =
OutputStream outputFile = new FileOutputStream(
filename.substring(filename.lastIndexOf('/')+1)
);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while((bytesRead = in.read(buffer)) > 0) {
outputFile.write(buffer, 0, bytesRead);
buffer = new byte[1024];
}
outputFile.close();
in.close();
con.close();
}
} catch (IOException e) {
System.err.println(e);
}
}
}
I guess that i should somehow look for \r\n\r\n as it indicates the empty line just before the content begins. So far this program creates a file which contains all of the http-response.
The recommended way to do this is to NOT try to talk to a web server using a plain Socket. Use one of the existing client-side HTTP stack; e.g. the standard HttpUrlConnection stack or the Apache HttpClient stack.
If you insist on talking using a plain socket, then it is up to you to process / deal with the "Header" lines in any response ... and everything else ... in accordance with the HTTP specification.
I guess that I should somehow look for \r\n\r\n as it indicates the empty line just before the content begins.
Yup ...
And you also potentially need to deal with the server sending a compressed response, an response using an unexpected character set, a 3xx redirect, and so on.
It seems that using curl and most web browsers my server code is closing the connection before the client is able to read the response. Here is my code
public void run() {
try {
InputStream input = clientSocket.getInputStream();
OutputStream output = clientSocket.getOutputStream();
System.out.println(input);
// getRequestObject(input);
long time = System.currentTimeMillis();
output.write(("HTTP/1.1 200 OK\n\nWorkerRunnable: " + this.serverText + " - " + time + "").getBytes());
output.flush();
output.close();
input.close();
System.out.println("Request processed: " + time);
} catch (IOException e) {
// report exception somewhere.
e.printStackTrace();
}
}
protected String readInputStream(InputStream input) throws IOException {
String inputLine;
BufferedReader in = new BufferedReader(new InputStreamReader(input));
StringBuilder sb = new StringBuilder();
while (!(inputLine = in.readLine()).equals("")) {
sb.append(inputLine);
}
return sb.toString();
}
Any thoughts?
Perhaps the problem could be caused by the fact that you're not reading the client's data. The client is trying to send you HTTP headers, but you immediately start sending the response. Try reading from the InputStream until you receive an empty line (which signals the end of the request HTTP headers) and then start sending the output.
If you need to embed an HTTP server in your application, I strongly recommend you to use an existing library. Implementing your own HTTP compliant server is going to be tedious work. See
Create a simple HTTP server with Java?
NanoHTTPD
I'm writing a little Java app which implements an http service that receives http post commands from a client.
The class I'm using to implement all of this is HttpHandler and HttpServer in the com.sun.net. package.
Now I'm implementing an handle(HttpExchange exchange) function which handles the request, and I'm having truble reading the post values received by the request because the only access that I have to these values is via HttpExchange.getResponseBody() which is just an output stream.
I'm looking to parse text post values and uploaded files.
I have written classes that process multipart requests for my project Sceye-Fi, an HTTP server that uses the com.sun.net.httpserver classes that come with java 6, to receive photo uploads from an Eye-Fi card.
This can help with file uploads (multipart posts).
For a non-multipart post, you would need to do something like this:
// determine encoding
Headers reqHeaders = exchange.getRequestHeaders();
String contentType = reqHeaders.getFirst("Content-Type");
String encoding = "ISO-8859-1";
if (contentType != null) {
Map<String,String> parms = ValueParser.parse(contentType);
if (parms.containsKey("charset")) {
encoding = parms.get("charset");
}
}
// read the query string from the request body
String qry;
InputStream in = exchange.getRequestBody();
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte buf[] = new byte[4096];
for (int n = in.read(buf); n > 0; n = in.read(buf)) {
out.write(buf, 0, n);
}
qry = new String(out.toByteArray(), encoding);
} finally {
in.close();
}
// parse the query
Map<String,List<String>> parms = new HashMap<String,List<String>>();
String defs[] = qry.split("[&]");
for (String def: defs) {
int ix = def.indexOf('=');
String name;
String value;
if (ix < 0) {
name = URLDecoder.decode(def, encoding);
value = "";
} else {
name = URLDecoder.decode(def.substring(0, ix), encoding);
value = URLDecoder.decode(def.substring(ix+1), encoding);
}
List<String> list = parms.get(name);
if (list == null) {
list = new ArrayList<String>();
parms.put(name, list);
}
list.add(value);
}
An alternative would be using HttpService from HttpCore.
There is a Basic HTTP server example in the documentation