I am trying to call my HttpServer with a POST and send a message in the body, on the server side I can see that it is called twice and I cannot figure out why.
Here is a part of the client code
String URL = "http://localhost:8081/" + path +"/service?session=" + sessionId;
connection = openConnection(URL, "POST");
OutputStream output = connection.getOutputStream();
output.write("Some Random body data".getBytes());
output.close();
stream = connection.getInputStream();
stream.close();
connection.disconnect();
On the server side i can see that the service is called two times. I figure it has to do something with my OutputStream and InputStream, but if i dont call the input stream it wont call the service any time.
EDIT!!!
Here is some more code
public class Server {
private static final int BASE_PORT = 8081;
public static void main(String[] args) {
try{
InetSocketAddress address = new InetSocketAddress(BASE_PORT);
HttpServer server = HttpServer.create(address, 0);
server.createContext("/", new PathDelegator());
server.setExecutor(Executors.newCachedThreadPool());
server.start();
System.out.println("Server is listening on : " + BASE_PORT);
}catch(IOException e){
e.printStackTrace();
}
}
}
public class PathDelegator implements HttpHandler{
public void handle(HttpExchange exchange) throws IOException {
String URI = exchange.getRequestURI().toString();
if(URI.indexOf("/session") != -1){
//Call ServiceHandler
System.out.println("Call ServiceHandler");
serviceHandler(exchange, "some session key");
}
}
private void serviceHandler(HttpExchange exchange, String sessionId) throws IOException{
String requestMethod = exchange.getRequestMethod();
OutputStream responseBody = exchange.getResponseBody();
if(requestMethod.equalsIgnoreCase("POST")){
Headers responseHeaders = exchange.getResponseHeaders();
responseHeaders.set("Content-Type", "text/plain");
InputStream stream = exchange.getRequestBody();
int b = 0;
StringBuffer buffer = new StringBuffer();
while((b = stream.read()) != -1){
buffer.append((char)b);
}
System.out.println("body data: " + buffer.toString());
exchange.sendResponseHeaders(200, 0);
}else {
exchange.sendResponseHeaders(400, 0);
}
responseBody.close();
}
}
public class ClientTest {
#Test
public void shouldBeAbleToPostToService(){
try {
String SCORE_URL = "http://localhost:8081/service?session=" + sessionId;
connection = openConnection(URL, "POST");
OutputStream output = connection.getOutputStream();
output.write("Some body data".getBytes());
output.close();
stream = connection.getInputStream();
stream.close();
connection.disconnect();
fail("Not implemented yet!");
} catch (IOException e) {
e.printStackTrace();
}
}
private HttpURLConnection openConnection(String url, String method) throws IOException{
URL connectionURL = new URL(url);
HttpURLConnection connection = (HttpURLConnection)connectionURL.openConnection();
connection.setRequestMethod(method);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
return connection;
}
}
Finallty i see that the System.out.println("body data: " + buffer.toString()); is outputted two times
Well, i finally figured out what was going on...
i had a method
public synchronized boolean addValue(int id, int value){
Integer previous = values.put(id, value);
return previous.intValue() != value;
}
problem was that the first time, the put would return a NULL value and as soon as i took care of this method the error does not occur no more.
Related
I have created HTTP server in Java, and tested posting plain string and received response successfully, but I don't know how to read the file on Server-Side which i posted from client side, I tried BuffuredReader and InputStream code but the browser keeps on loading my page and shows nothing.
Server Side Code :
public class Server {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/ahmer", new MyHandler());
server.setExecutor(null);
server.start();
}
static class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange t) throws IOException {
String response = "Success";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
Client Side Code :
URL url = new URL("http://localhost:8080/ahmer");
HttpURLConnection con = (HttpURLConnection)url.openConnection();
String document = "C:\\ahmer.xml";
FileReader fr = new FileReader(document);
// specify that we will send output and accept input
con.setDoInput(true);
con.setDoOutput(true);
char[] buffer = new char[1024*10];
int b_read = 0;
con.setRequestProperty ( "Content-Type", "text/xml" );
con.setRequestProperty("SOAPAction","MSMQMessage");
con.setRequestProperty("Proxy-Accept","NonInteractiveClient" );
con.setRequestProperty("CONNECTION", "close");
con.setRequestProperty("CACHE-CONTROL", "no-cache");
con.setRequestProperty("USER-AGENT", "OpenTV-iAdsResponder_1_0");
OutputStreamWriter writer = new OutputStreamWriter( con.getOutputStream() );
while ((b_read = fr.read(buffer)) != -1) {
writer.write(buffer, 0, b_read);
}
writer.flush();
writer.close();
fr.close();
int i = con.getResponseCode();
rs=String.format("Response code: %d",i);
HttpClient client = new DefaultHttpClient();
HttpGet requests = new HttpGet("http://localhost:8080/ahmer");
HttpResponse rss = client.execute(requests);
String responseAsString = EntityUtils.toString(rss.getEntity());
con.disconnect();
Here is my code to read the xml file sent from client to server.
static class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange t) throws IOException {
InputStream xml = t.getRequestBody();
final char[] buffer = new char[1024];
final StringBuilder out = new StringBuilder();
try (Reader in = new InputStreamReader(xml, "UTF-8")) {
for (;;) {
int rsz = in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}
}
catch (UnsupportedEncodingException ex) {
/* ... */
}
catch (IOException ex) {
/* ... */
}
}
I'm trying to post HTTP from android. If I'll request using that C# code in LINQPAD it works
void Main()
{
string r = String.Format(#"<s:Body><TrackMobileApp xmlns=""soap action url"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><device>test</device><imei>test</imei><ipAddress>127.0.0.1</ipAddress><timeStamp>2016-02-17T17:32:00.5147663+04:00</timeStamp></TrackMobileApp></s:Body>", DateTime.Now.ToString("o"));
HttpWebRequest wr = (HttpWebRequest)HttpWebRequest.Create("URL.asmx");
wr.ProtocolVersion = HttpVersion.Version11;
wr.Headers.Add("SOAPAction", "soap action");
wr.Method = "POST";
wr.ContentType = "text/xml;charset=utf-8";
using (StreamWriter sw = new StreamWriter(wr.GetRequestStream()))
{
sw.Write(r);
}
HttpWebResponse rs = (HttpWebResponse)wr.GetResponse();
if (rs.StatusCode == HttpStatusCode.OK)
{
XmlDocument xd = new XmlDocument();
using (StreamReader sr = new StreamReader(rs.GetResponseStream()))
{
xd.LoadXml(sr.ReadToEnd());
xd.InnerXml.Dump();
}
}
}
But from android it gives me http 415. What's wrong?
I have this in onCreate
new DownloadTask().execute("URL.asmx");
and my methods are:
private class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
//do your request in here so that you don't interrupt the UI thread
try {
return downloadContent(params[0]);
} catch (IOException e) {
return "Unable to retrieve data. URL may be invalid.";
}
}
#Override
protected void onPostExecute(String result) {
//Here you are done with the task
}
}
private String downloadContent(String myurl) throws IOException {
InputStream is = null;
int length = 500;
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestProperty("SOAPAction", "soap action");
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/xml");
conn.setDoInput(true);
conn.connect();
int response = conn.getResponseCode();
Log.d(TAG, "The response is: " + response);
is = conn.getInputStream();
// Convert the InputStream into a string
String contentAsString = convertInputStreamToString(is, length);
return contentAsString;
} finally {
if (is != null) {
is.close();
}
}
}
public String convertInputStreamToString(InputStream stream, int length) throws IOException, UnsupportedEncodingException {
Reader reader = null;
reader = new InputStreamReader(stream, "UTF-8");
char[] buffer = new char[length];
reader.read(buffer);
return new String(buffer);
}
I'm trying to study client/server using java. Need you help guys. Thanks in advance.
I built a proxy server that connects to the browser, what I would like to do is when it connects to the browser it will cache or download the webpage that the browser visited. Is it possible? Any tips or materials you can suggest? if possible, a sample code would be perfect because I really don't have any idea on how to do it.
Here is my code for my proxy server.
import java.io.*;
import java.net.*;
import java.util.*;
public class test extends Thread {
Socket connectedClient = null;
BufferedReader inFromClient = null; // request from the client (browser)
DataOutputStream outToClient = null; // response to client (browser)
public test(Socket client) {
connectedClient = client;
}
public void run() {
try {
System.out.println( "The Client "+
connectedClient.getInetAddress() + ":" + connectedClient.getPort() + " is connected");
inFromClient = new BufferedReader(new InputStreamReader (connectedClient.getInputStream()));
outToClient = new DataOutputStream(connectedClient.getOutputStream());
String requestString = inFromClient.readLine();
String headerLine = requestString;
StringTokenizer tokenizer = new StringTokenizer(headerLine);
String httpMethod = tokenizer.nextToken();
String httpQueryString = tokenizer.nextToken();
StringBuffer responseBuffer = new StringBuffer();
responseBuffer.append("The HTTP Client request is ....<BR>");
System.out.println("The HTTP request string is ....");
while (inFromClient.ready())
{
// Read the HTTP complete HTTP Query
responseBuffer.append(requestString + "<BR>");
System.out.println(requestString);
requestString = inFromClient.readLine();
}
if (httpMethod.equals("GET")) {
if (httpQueryString.equals("/")) {
// The default home page
httprequest(200, responseBuffer.toString());
} else {
//filename : request from the client
String fileName = httpQueryString;
fileName = URLDecoder.decode(fileName);
System.out.println("Request:" + fileName);
httprequest(200,fileName);
}
}
else httprequest(404, "<b>The Requested resource not found ....</b>");
} catch (Exception e) {
e.printStackTrace();
}
}
public void httprequest(int statusCode,String location) throws Exception {
HttpURLConnection connection = null;
StringBuilder sb = null;
String line = null;
URL serverAddress = null;
String statusLine = null;
String serverdetails = "Server: Java ProxyServer";
String contentTypeLine = "Content-type: text/html\n\n";
if (statusCode == 200)
{
statusLine = "HTTP/1.1 200 OK" + "\r\n";
try {
serverAddress = new URL(location);
connection = null;
connection = (HttpURLConnection)serverAddress.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.connect();
//read the result from the server
InputStream rd = connection.getInputStream();
outToClient.writeBytes(statusLine);
outToClient.writeBytes(serverdetails);
outToClient.writeBytes(contentTypeLine);
outToClient.writeBytes("\r\n");
byte[] buffer = new byte[1024] ;
int bytesRead;
while ((bytesRead = rd.read(buffer)) != -1 ){
outToClient.write(buffer, 0, bytesRead);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
}
}
else{
statusLine = "HTTP/1.1 404 Not Found" + "\r\n";
outToClient.writeBytes(statusLine);
outToClient.writeBytes(serverdetails);
outToClient.writeBytes(contentTypeLine);
}
outToClient.close();
}
public static void main (String args[]) throws Exception {
//System.setProperty("http.proxyHost","172.16.1.254") ;
// System.setProperty("http.proxyPort", "3128") ;
ServerSocket Server = new ServerSocket (8080, 0, InetAddress.getByName("localhost"));
System.out.println ("Proxy Server Waiting for client on port 8080");
while(true) {
Socket connected = Server.accept();
(new test(connected)).start();
}
}
}
I hope you want monitor HTTP trafic, Take a reference from this, http://www.java2s.com/Code/Java/Network-Protocol/Asimpleproxyserver.htm even I built by my own by taking references from this kinda resources. But SSL communication you cannot do monitoring.
I just try to post data to google by using the following code,but always got 405 error,can anybody tell me way?
package com.tom.labs;
import java.net.*;
import java.io.*;
public class JavaHttp {
public static void main(String[] args) throws Exception {
File data = new File("D:\\in.txt");
File result = new File("D:\\out.txt");
FileOutputStream out = new FileOutputStream(result);
OutputStreamWriter writer = new OutputStreamWriter(out);
Reader reader = new InputStreamReader(new FileInputStream(data));
postData(reader,new URL("http://google.com"),writer);//Not working
//postData(reader,new URL("http://google.com/search"),writer);//Not working
sendGetRequest("http://google.com/search", "q=Hello");//Works properly
}
public static String sendGetRequest(String endpoint,
String requestParameters) {
String result = null;
if (endpoint.startsWith("http://")) {
// Send a GET request to the servlet
try {
// Send data
String urlStr = endpoint;
if (requestParameters != null && requestParameters.length() > 0) {
urlStr += "?" + requestParameters;
}
URL url = new URL(urlStr);
URLConnection conn = url.openConnection();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
result = sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(result);
return result;
}
/**
* Reads data from the data reader and posts it to a server via POST
* request. data - The data you want to send endpoint - The server's address
* output - writes the server's response to output
*
* #throws Exception
*/
public static void postData(Reader data, URL endpoint, Writer output)
throws Exception {
HttpURLConnection urlc = null;
try {
urlc = (HttpURLConnection) endpoint.openConnection();
try {
urlc.setRequestMethod("POST");
} catch (ProtocolException e) {
throw new Exception(
"Shouldn't happen: HttpURLConnection doesn't support POST??",
e);
}
urlc.setDoOutput(true);
urlc.setDoInput(true);
urlc.setUseCaches(false);
urlc.setAllowUserInteraction(false);
urlc.setRequestProperty("Content-type", "text/xml; charset=UTF-8");
OutputStream out = urlc.getOutputStream();
try {
Writer writer = new OutputStreamWriter(out, "UTF-8");
pipe(data, writer);
writer.close();
} catch (IOException e) {
throw new Exception("IOException while posting data", e);
} finally {
if (out != null)
out.close();
}
InputStream in = urlc.getInputStream();
try {
Reader reader = new InputStreamReader(in);
pipe(reader, output);
reader.close();
} catch (IOException e) {
throw new Exception("IOException while reading response", e);
} finally {
if (in != null)
in.close();
}
} catch (IOException e) {
e.printStackTrace();
throw new Exception("Connection error (is server running at "
+ endpoint + " ?): " + e);
} finally {
if (urlc != null)
urlc.disconnect();
}
}
/**
* Pipes everything from the reader to the writer via a buffer
*/
private static void pipe(Reader reader, Writer writer) throws IOException {
char[] buf = new char[1024];
int read = 0;
while ((read = reader.read(buf)) >= 0) {
writer.write(buf, 0, read);
}
writer.flush();
}
}
405 means "method not allowed". For example, if you try to POST to a URL that doesn't allow POST, then the server will return a 405 status.
What are you trying to do by making a POST request to Google? I suspect that Google's home page only allows GET, HEAD, and maybe OPTIONS.
Here's the body of a POST request to Google, containing Google's explanation.
405. That’s an error.
The request method POST is inappropriate for the URL /. That’s all we know.
I wrote this HttpRequest method, but for some reason it always goes to 404 Not Found, even though the file location exists when the java process isn't running.
import java.io.*;
import java.net.*;
import java.util.*;
final class HttpRequest implements Runnable {
final static String CRLF = "\r\n";
Socket socket;
// Constructor
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
// Implement the run() method of the Runnable interface.
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private static void sendBytes(FileInputStream fis, OutputStream os)
throws Exception {
// Construct a 1K buffer to hold bytes on their way to the socket.
byte[] buffer = new byte[1024];
int bytes = 0;
// Copy requested file into the socket's output stream.
while((bytes = fis.read(buffer)) != -1 ) {
os.write(buffer, 0, bytes);
}
}
private static String contentType(String fileName) {
if(fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
if(fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")) {
return "image/jpeg";
}
if(fileName.endsWith(".gif")) {
return "image/gif";
}
return "application/octet-stream";
}
private void processRequest() throws Exception {
// Get a reference to the socket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
// Set up input stream filters.
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// Get the request line of the HTTP request message.
String requestLine = new String(br.readLine());
// Display the request line.
System.out.println();
System.out.println(requestLine);
// Get and display the header lines.
String headerLine = null;
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
// Extract the filename from the request line.
StringTokenizer tokens = new StringTokenizer(requestLine);
tokens.nextToken(); // skip over the method, which should be "GET"
String fileName = tokens.nextToken();
// Prepend a "." so that file request is within the current directory.
fileName = "." + fileName;
// Open the requested file.
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
// Construct the response message.
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "200 OK" + CRLF;
contentTypeLine = "Content-type: " +
contentType( fileName ) + CRLF;
} else {
statusLine = "404 NOT FOUND" + CRLF;
contentTypeLine = "Content Not Found!" + CRLF;
entityBody = "<HTML>" +
"<HEAD><TITLE>Not Found</TITLE></HEAD>" +
"<BODY>Not Found</BODY></HTML>";
}
// Send the status line.
os.writeBytes(statusLine);
// Send the content type line.
os.writeBytes(contentTypeLine);
// Send a blank line to indicate the end of the header lines.
os.writeBytes(CRLF);
// Send the entity body.
if (fileExists) {
sendBytes(fis, os);
fis.close();
} else {
os.writeBytes("File DNE: Content Not Found!");
}
// Close streams and socket.
os.close();
br.close();
socket.close();
}
}
Any help would be greatly appreciated...I feel like it's something simple I'm missing.
I ran your code; it works fine (except for some minor issues with not printing the headers correctly, which every browser I've tried is willing to completely ignore).
Are you sure your working directory is where you expect? Try changing the 404 message to something like:
contentTypeLine = "Content Not Found: " + new File(fileName).getAbsolutePath() + CRLF;
For reference, I ran it with a test harness of:
public static void main(String[] args) throws Exception {
final ServerSocket ss = new ServerSocket(8080);
while (true)
new HttpRequest(ss.accept()).run();
}