0

my problem is, i can't read the text from a given URL using HTTP sockets. For example i want to read from 88.88.8.8/text.txt and print the contents on command line yet it get stuck at the reading part without any errors:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Base64;

public class Program {

    static final int PORT_NO = 80;

    static Socket m_socket;

    static String m_server;
    static String m_index;
    static String m_authString;

    public static void main(String[] args) throws IOException {

        try {        
            setConnectionInfoFromArgs(args);         
            m_socket = new Socket(m_server, PORT_NO);

            loginToServer();

            PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(m_socket.getOutputStream()))); 
            out.print("GET /" + m_index + " HTTP/1.1"); 
            out.print("\r\n");
            out.flush();

            BufferedReader input = new BufferedReader(new InputStreamReader(m_socket.getInputStream()));
            String line;

            while((line = input.readLine()) != null) {
                System.out.println(line); //Gets stuck here
            }
        } catch (Exception e) {
            System.out.println("Unable to connect!");
            System.out.println("Be sure to enter correct URL and authentication.");
        }
        finally {
            System.exit(0);
        }
    }

    public static void setConnectionInfoFromArgs(String[] args) {
        String[] url = args[0].split("/");
        m_server = url[0];
        m_index = url[1];

        //Encode "userName:password" to Base64
        byte[] encodedBytes = Base64.getEncoder().encode(args[1].getBytes());
        m_authString = new String(encodedBytes);
    }

    private static void loginToServer() throws IOException {       
          DataOutputStream auth = new DataOutputStream(m_socket.getOutputStream());
          auth.writeBytes("Authorization: Basic " + m_authString);
    }
}
  • DON'T SEND PASSWORDS OVER THE INTERNET WITH ONLY BASE64 ECRYTPTION! THAT IS __NOT__ SAFE! – Jerfov2 Mar 22 '17 at 12:24
  • 1
    @Jerfov2 Base64 is no "encryption" - it is encoding. And while your advice is valid, writing in all caps is commonly seen as to represent "screaming" - which is rude. – Fildor Mar 22 '17 at 12:26
  • @Fildor Just wanted to get the point across ;) – Jerfov2 Mar 22 '17 at 12:27
  • 1
    For all we know it might be an internal website. – Steve Smith Mar 22 '17 at 12:28
  • 1
    @Jerfov2 I thought so, yes and again: the advice is good. But if you want to stress a point there is _italic_ and **bold** which is not considered rude in contrast to all caps :) That's like burping to show the meal was tasty. – Fildor Mar 22 '17 at 12:30
  • 2
    Proper Coder: add another "\r\n" to your request. It should be ""GET /" + m_index + " HTTP/1.1\r\n\r\n"" – Fildor Mar 22 '17 at 12:38
  • @Fildor i have changed it to out.print("GET /" + m_index + " HTTP/1.1\r\n\r\n"); i got 400 Bad Request. – Proper Coder Mar 22 '17 at 12:48
  • Better than nothing ;) Have a look at what it looks like when m_index is inserted. – Fildor Mar 22 '17 at 13:02
  • @ProperCoder: You are getting the `400` because you are sending an HTTP **1.1** request without the **required** `Host` header. You need to add that: `out.print("GET /" + m_index + " HTTP/1.1\r\nHost: " + m_server + "\r\n\r\n"); out.flush();` Otherwise use HTTP **1.0** instead: `out.print("GET /" + m_index + " HTTP/1.0\r\n\r\n"); out.flush();` That being said, there are plenty of HTTP client libraries available for Java, you really should not be implementing HTTP manually. It is not a trivial protocol to implement from scratch. Your response handling is not even remotely close to being correct – Remy Lebeau Mar 22 '17 at 22:13
  • @ProperCoder: see the pseudo-code in [this answer](http://stackoverflow.com/a/7234357/65863) for the kind of logic you need to implement when receiving an HTTP server's response. – Remy Lebeau Mar 22 '17 at 22:21

1 Answers1

0

Ok i did some research and turns out both my Host header was lacking as Remy Lebeau said and also the authorization part wasn't properly included in the header. The code below fixed the issue:

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(m_socket.getOutputStream())), false);
            out.print("GET /" + m_index + " HTTP/1.1\r\n"
                    + "Host: " + m_server + "\r\n"
                    + "Authorization: Basic " + m_authString + "\r\n"
                    + "Connection: close\r\n\r\n");
            out.flush();