HTTP Authentication JAVA - java

I need to know what is the problem in the following code
public class NewClass {
public static void main(String[] args) {
try {
while (true) {
ServerSocket ss = new ServerSocket(7777);
Socket c = ss.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(c.getInputStream()));
DataOutputStream writer = new DataOutputStream(c.getOutputStream());
String temp;
// read browser Request
while ((temp = reader.readLine()) != null) {
System.out.println(temp);
}
// send basic authentication request
String response = "WWW-Authenticate: Basic realm=\"test\"\n";
respons += "HTTP/1.1 401 Authorization Required\n";
writer.writeBytes(response );
writer.flush();
// receive browser response
while ((temp = reader.readLine()) != null) {
System.out.println(temp);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
when i request http://localhost:7777 from browser, the authentication dialog does not appear
why ????
also i'm tried to send this
String response = "HTTP/1.1 401 Authorization Required\n";
response += "WWW-Authenticate: Basic realm=\"test\"\n";
also i sent full server response and without benefits

The reader.readLine() will not return null until it reaches the EOF so you are blocked reading in the first loop and never send anything to the browser.
In the first loop look for an empty string or null.
while ((temp = reader.readLine()) != null) {
if( temp.length() == 0 ) break;
System.out.println(temp);
}

It works fine
String response = "WWW-Authenticate: Basic realm=\"test\"\r\n";
respons += "HTTP/1.1 401 Authorization Required\r\n\r\n";
writer.writeBytes(response );
writer.flush();
but one one problem faced me, how to tell server to wait until browser send basic http authentication.
in my case browser request a new http request.
Thanks

Related

Http client receives no response when server reads only headers from request

I'm messing around with HTTP and sockets in Java and was hoping you could shed some light on this:
When my HTTP server written in Java SE 11 does not read the entire request and then responds, the client does not get it or gets an error. Why is that? Is the client unable to read the response before the server has read the entire request? If the call to readBody is executed in the snippet below, this works fine. It also works fine if the response has the Content-Length header and a text body. That is actually more puzzling to me.
My example request is a POST with the data fds. Postman says "Could not get any request" and curl says "curl: (56) Recv failure: Connection reset by peer".
import java.io.*;
import java.net.Socket;
import java.util.*;
class Handler {
public synchronized void read(Socket incoming) {
try (incoming;
OutputStream outputStream = incoming.getOutputStream();
InputStream inputStream = incoming.getInputStream();
PrintWriter pw = new PrintWriter(outputStream)) {
writeRequest(inputStream);
pw.print("HTTP/1.1 200 OK\r\n");
pw.print("\r\n");
pw.flush();
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage());
e.printStackTrace();
}
}
private void writeRequest(InputStream inputStream) throws IOException {
String verbLine = readLine(inputStream);
Map<String, String> headers = readHeaders(inputStream);
//readBody(inputStream, headers);
}
private void readBody(InputStream inputStream, Map<String, String> headers) throws IOException {
Optional<String> optKey = headers.keySet().stream()
.filter(k -> k.equalsIgnoreCase("Content-Length"))
.findFirst();
if (optKey.isPresent()) {
int contentLength = Integer.parseInt(headers.get(optKey.get()));
byte[] bytes = inputStream.readNBytes(contentLength);
}
}
private Map<String, String> readHeaders(InputStream inputStream) throws IOException {
Map<String, String> headers = new HashMap<>();
while (true) {
String line = readLine(inputStream);
if (line == null || line.isEmpty()) {
return headers;
}
String key = line.split(":")[0].trim();
String value = line.split(":")[1].trim();
headers.put(key, value);
}
}
private String readLine(InputStream inputStream) throws IOException {
byte[] buf = new byte[200];
int offset = 0;
while (true) {
int read = inputStream.read();
if (read == -1) {
return null;
}
buf[offset] = (byte) read;
if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n')) {
return "";
}
if (buf[offset] == 0x0A) {
int endOfLine = buf[offset - 1] == 0x0D ? offset - 1 : offset;
return new String(buf, 0, endOfLine);
} else {
offset++;
}
}
}
}
If you close a socket at the server while there are still unread data it will result in a connection reset error at the client. This happens here since you don't read the full request. This error will be exposed to the user if the full response from the server was not read yet.
If you send the response with a content-length and then the full body then the client will have read the full response and thus the error will be ignored. If instead you send neither content-length nor use chunked encoding the client will expect the response to end with a proper close of the TCP connection. In this case the connection reset will be propagated to the user since the full response from the server was not (properly) read yet.
Your response needs to have either a Content-Length header or a Transfer-Encoding header - which tells the client how the response will be transmitted and allows it to figure out when all the bytes have been received. Without that it will need to wait for EOF and assume that the response body is terminated by EOF (this for compatibility with HTTP/1.0). It is possible that your client doesn't support that.
It might help to know which client you are using.

Java web server can listen to requests but not send responses

This is part of the program that is having trouble.
public void run() {
while(!isStopped) {
try {
socket = server.accept();
System.out.println(socket.getRemoteSocketAddress() + " has connected");
//problem starts
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String request;
while((request = in.readLine()) != null) {
System.out.println(request);
} //problem ends
FileReader f = new FileReader("html/index.html");
BufferedReader br = new BufferedReader(f);
String response;
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
out.write("HTTP/1.1 200 OK\r\n");
out.write("Content-type: text/html\r\n");
out.write("\r\n");
while((response = br.readLine()) != null) {
out.write(response);
}
out.close();
socket.close();
} catch(Exception e) {
System.out.println(e);
e.printStackTrace();
}
}
I created a java web server and it works fine with all the connections. But when the program listens to the request from client and print that request on the console, the program doesn't continue and so it doesn't respond with the HTML file. I tried getting rid of the printing the request part and the program easily sends the HTML but I don't like that because it doesn't print the initial request. How can I make the server properly listen and print client requests and send responses back accordingly and continue like this in a loop? It would be great to show the codes.

Sending HTTP request's

I am writing a web client. I have the following code.
public class Connection extends Thread{
public final static int PORT = 1337;
private ServerSocket svrSocket = null;
private Socket con = null;
public Connection(){
try{
svrSocket = new ServerSocket(PORT);
System.out.println("Conected to: " + PORT);
}catch(IOException ex)
{
System.err.println(ex);
System.out.println("Unable to attach to port");
}
}
public void run(){
while(true)
{
try{
con = svrSocket.accept();//on this part the program stops
System.out.println("Client request accepted");
PrintWriter out = new PrintWriter(con.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
out.println("GET /<index.html> HTTP/1.1");
out.println("***CLOSE***");
System.out.println(in.readLine());
/*
String s;
while((s = in.readLine()) != null)
{
System.out.println(s);
}*/
out.flush();
out.close();
in.close();
con.close();
System.out.println("all closed");
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
}
The run method will be used latter on. That I have is a file called index.html. This file is in the same file as the java code. What I am trying to do with the request is send the HTML file. But if I run this program on a web browser localhost:1337 the following gets displayed.
GET /<index.html> HTTP/1.1
***CLOSE***
This should not get displayed. The page that results of the HTML code in the index.html should get displayed.
Index.html code:
<html>
<head>
<title> </title>
</head>
<body bgcolor = "#ffffcc" text = "#000000">
<h1>Hello</h1>
<p>This is a simple web page</p>
</body>
</html>
How do I get this html page to display in the browser?
Thank you
t seems that all is good on your code, it seems you need to read the HTTP header from the input stream so you can get the requested file name and then use the Socket output stream to write the response from the file.
OutputStream output = con.getOutputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String fileName = readHeader(in);
String baseDir = System.getProperty("my.base.dir", "/home/myname/httpserver");
boolean exist = true;
InputStream fileIn = null;
try {
File requestedFile = new File(baseDir, fileName);
fileIn = new FileInputStream(requestedFile);
} catch(Exception e){
exist = false;
}
String server = "Java Http Server";
String statusLine = null;
String typeLine = null;
String body = null;
String lengthLine = "error";
if (exist) {
statusLine = "HTTP/1.0 200 OK" + "\r\n";
//get content type by extension
typeLine = "Content-type: html/text \r\n";
lengthLine = "Content-Length: " + (new Integer(fileIn.available())).toString() + "\r\n";
} else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
typeLine = "text/html";
body = "<HTML>" + "<HEAD><TITLE>404</TITLE></HEAD>" + "<BODY>404 Not Found"+"</BODY></HTML>";
}
output.write(statusLine.getBytes());
output.write(server.getBytes());
output.write(typeLine.getBytes());
output.write(lengthLine.getBytes());
output.write("\r\n".getBytes());
if (exist) {
byte[] buffer = new byte[1024];
int bytes = 0;
while ((bytes = fileIn.read(buffer)) != -1) {
output.write(buffer, 0, bytes);
}
} else {
output.write(body.getBytes());
}
//close sreams
You are confusing a couple of things. First of all: what you are writing is a server, not a client.
Second: You are not following the HTT Protocol.
The line GET /<index.html> HTTP/1.1 (which is wrong, it should be GET /index.html HTTP/1.1) is a request that is sent by the client (like a web browser). Instead, it is your server sending this.
A quick solution:
Instead of sending this static text (the line with the GET and the one with the ***CLOSE***), read the content of your index.html file and print it to your out stream.
EDIT: Here's a quick overview of the http data flow:
The client (e.g. a browser) connects to the server
The client sends it's request, something like
GET /theFileIWant.html HTTP/1.1\r\n
Host: localhost\r\n
\r\n
at this point, the client usually stops sending anything and waits for the server to respond. That is called the "request/response" model.
The server reads the request data and finds out what it has to do.
The output (in this case: a file's content) is sent to the client, preceded by HTTP response headers.
The connection can be kept open or closed, depending on the HTTP headers of both client's request and server's response.

HTTP Proxy Server Java error

As an assignment, I am allowed to use ServerSocket and Socket class only. Also it should be single-threaded as well.
I'm implementing a HTTP proxy server in Java, first it fetches request from client and then pushes to server, and then pushes the response back to the client.
The problem
The problem is, I have successfully get the request, send it to the end-server and get the proper HTTP response. I also can do print out the response in console. But it got stuck when I send the response to clientServer.outputstream. Firefox (requested to use, HTTP 1.0, no keep-alive requested) seems to load forever and nothing shows, and no response Firefox received from my program as well.
What I inspect when debug
Everytime a page start to load (FF request), there are always 2 client sockets. First socket contains null request, and second socket contains proper request. What I expect was that only one proper HTTP request from Firefox. Is that a weird behavior?
example:
/0:0:0:0:0:0:0:1:65194
[null request]
/0:0:0:0:0:0:0:1:65195
GET http://www.microsoft.com/ HTTP/1.0
Host: www.microsoft.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Proxy-Connection: close
Cookie: viewkey=lightweight; WT_FPC=id=269eb0e7618962f93a81347585923074:lv=1349229942007:ss=1349229580158; WT_NVR_RU=0=technet|msdn:1=:2=; omniID=c736269c_f430_4e9b_a42a_23a0c965c60a; MUID=212A1766CFE761423CD014BDCBE76158&TUID=1; MC1=GUID=08600fba7f5c5f409e67980d8a027593&HASH=ba0f&LV=20129&V=4&LU=1347643534618; A=I&I=AxUFAAAAAADGBwAA8ezRtqBBHjk3++mP1Bwj9w!!&V=4&CS=119EQ5002j10100; msdn=L=en-US
Code
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(60000);
while (true) {
clientSocket = serverSocket.accept();
[...]
// Extract request, and push to end-server
// Fetch response from end-server to client, using flush() already
// Close all input, output
// Close all sockets
} catch {[...]}
Any help is welcomed, thank you!
Full code as requested, I use PrintWriter, but before that using Byte makes no difference (not care efficiency)
import java.io.*;
import java.net.*;
import java.util.*;
public class Proxy {
static String separator = System.getProperty("line.separator");
public static void main(String args[]) {
//int port = Integer.parseInt(args[0]);
start(60000);
}
public static void start(int port) {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(port);
Socket clientSocket = null;
while (true) {
clientSocket = serverSocket.accept();
System.out.println(clientSocket.getRemoteSocketAddress() + "\n" + clientSocket.getLocalSocketAddress() + "\n" + clientSocket.getInetAddress());
BufferedReader inStreamFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inLine;
Vector<String> clientRequestHeader = new Vector<String>();
String rawRequest = "";
while ((inLine = inStreamFromClient.readLine()) != null) {
if (!inLine.isEmpty()) {
clientRequestHeader.add(inLine);
rawRequest = rawRequest.concat(inLine + separator);
} else break;
}
while ((inLine = inStreamFromClient.readLine()) != null)
rawRequest = rawRequest.concat(inLine + separator);
System.out.println(rawRequest);
if (!rawRequest.isEmpty()) {
handleRequest(clientSocket, clientRequestHeader, rawRequest);
} else {
//clientSocket.close();
// Not sure how to handle null request
}
}
} catch (Exception e) {e.printStackTrace();}
}
public static void handleRequest(Socket clientSocket, Vector<String> clientRequestHeader, String rawRequest) {
HTTPRequest request = new HTTPRequest(clientRequestHeader, rawRequest);
try {
//System.out.println(rawRequest);
// Send request to end-server
Socket endServerSocket = new Socket(request.getHost(), 80);
PrintWriter outStreamToEndServer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(endServerSocket.getOutputStream())));
BufferedReader stringReader = new BufferedReader(new StringReader(rawRequest));
String inLine;
while ((inLine = stringReader.readLine())!= null) {
outStreamToEndServer.println(inLine);
}
outStreamToEndServer.println();
outStreamToEndServer.flush();
// Read response header from end-server
String responseHeader = "";
BufferedReader inStreamFromEndServer = new BufferedReader(new InputStreamReader(endServerSocket.getInputStream()));
while (!(inLine = inStreamFromEndServer.readLine()).isEmpty()) {
responseHeader = responseHeader.concat(inLine + separator);
}
// Send response header to client
PrintWriter outStreamToClient = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())));
outStreamToClient.println(responseHeader);
outStreamToClient.flush();
// Send response body to client
String responseBody = "";
while ((inLine = inStreamFromEndServer.readLine()) != null) {
responseBody = responseBody.concat(inLine + separator);
}
outStreamToClient.println(responseBody);
outStreamToClient.flush();
endServerSocket.shutdownInput();
clientSocket.shutdownOutput();
clientSocket.close();
endServerSocket.close();
//endServerSocket = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
first you should not use PrintWriter to transfer the Data, because the HTTP protocol isn't a pure text protocol the body can contain some raw data like images.
Replace your response transfer code with the code below.
InputStream in = endServerSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1)
{
out.write(buffer, 0, bytesRead);
}
in.close();
out.close();
Second point, you add always as line break the
static String separator = System.getProperty("line.separator");
This is the System specific line seperator. HTTP defines for the HTTP header and for the http header and body separation the ctrl line break charaters, so change this.
static String separator = "\r\n";
With this changes you will get your response to your browser.
Last Point you should change your client request read code also, because it will not always work if you want POST some data. Sometimes this data will transfered as raw data, by example file uploads.
Good Luck

HTTP GET request not working in java when HTTP is 1.1?

so i made a little code that can download 4chan pages. i get the raw HTML page and parse it for my need. the code below was working fine but it suddenly stopped working. when i run it the server does not accept my request it seems its waiting for something more. however i know that HTTP request is as below
GET /ck HTTP/1.1
Host: boards.4chan.org
(extra new line)
if i change this format in anyway i revive "400 bad request" status code. but if i change HTTP/1.1 to 1.0 the server responses in "200 ok" status and i get the whole page. so this makes me thing the error is in the host line since that became mandatory in HTTP/1.1. but still i cannot figure out what exactly need to be changed.
the calling function simply this, to get one whole board
downloadHTMLThread( "ck", -1);
or for a specific thread u just change -1 to that number. for example like for the link below will have like below.
//http://boards.4chan.org/ck/res/3507158
//url.getDefaultPort() is 80
//url.getHost() is boards.4chan.org
//url.getFile() is /ck/res/3507158
downloadHTMLThread( "ck", 3507158);
any advise would be appreciated, thanks
public static final String BOARDS = "boards.4chan.org";
public static final String IMAGES = "images.4chan.org";
public static final String THUMBS = "thumbs.4chan.org";
public static final String RES = "/res/";
public static final String HTTP = "http://";
public static final String SLASH = "/";
public String downloadHTMLThread( String board, int thread) {
BufferedReader reader = null;
PrintWriter out = null;
Socket socket = null;
String str = null;
StringBuilder input = new StringBuilder();
try {
URL url = new URL(HTTP+BOARDS+SLASH+board+(thread==-1?SLASH:RES+thread));
socket = new Socket( url.getHost(), url.getDefaultPort());
reader = new BufferedReader( new InputStreamReader( socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
out.println( "GET " +url.getFile()+ " HTTP/1.1");
out.println( "HOST: " + url.getHost());
out.println();
long start = System.currentTimeMillis();
while ((str = reader.readLine()) != null) {
input.append( str).append("\r\n");
}
long end = System.currentTimeMillis();
System.out.println( input);
System.out.println( "\nTime: " +(end-start)+ " milliseconds");
} catch (Exception ex) {
ex.printStackTrace();
input = null;
} finally {
if( reader!=null){
try {
reader.close();
} catch (IOException ioe) {
// nothing to see here
}
}
if( socket!=null){
try {
socket.close();
} catch (IOException ioe) {
// nothing to see here
}
}
if( out!=null){
out.close();
}
}
return input==null? null: input.toString();
}
Try using Apache HttpClient instead of rolling your own:
static String getUriContentsAsString(String uri) throws IOException {
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(new HttpGet(uri));
return EntityUtils.toString(response.getEntity());
}
If you are doing this to really learn the internals of HTTP client requests, then you might start by playing with curl from the command line. This will let you get all your headers and request body squared away. Then it will be a simple matter of adjusting your request to match what works in curl.
By the code I think that you are sending 'HOST' instead of 'Host'. Since this is a compulsory header in http/1.1, but ignored in http/1.0, that might be the problem.
Anyway, you could use a program to capture the packet sent (i. e. wireshark), just to make sure.
Using println is quite useful, but the line separator appended to the command depends on the system property line.separator. I think (although I'm not sure) that the line separator used in http protocol has to be '\r\n'. If you're capturing the packet, I think it'd be a good idea to check that each line sent ends with '\r\n' (bytes x0D0A) (just in case your os line separator is different)
Use www.4chan.org as the host instead. Since boards.4chan.org is a 302 redirect to www.4chan.org, you won't be able to scrape anything from boards.4chan.org.

Categories