Я не могу использовать API Reddit для входа - PullRequest
5 голосов
/ 14 ноября 2011

Я пытаюсь использовать Reddit API для некоторых вещей.У меня все работает, но меняю страницы и захожу.

Мне нужно войти в систему, чтобы использовать мою программу, я знаю, как использовать полученный файл cookie, но мне просто не удается войти.

Вот код:

public static Login POST(URL url, String user, String pw) throws IOException
{

    String encodedData =  URLEncoder.encode("api_type=json&user=" + user +"&passwd="+pw, "UTF-8");
    HttpURLConnection ycConnection = null;
    ycConnection = (HttpURLConnection) url.openConnection();
    ycConnection.setRequestMethod("POST");
    ycConnection.setDoOutput(true);
    ycConnection.setUseCaches (false);
    ycConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
    PrintWriter out = new PrintWriter(ycConnection.getOutputStream());


    out.print(encodedData.getBytes());
    out.close();

    BufferedReader in = new BufferedReader(new InputStreamReader(ycConnection.getInputStream()));
    String response = in.readLine();

    Map<String, List<String>> headers = ycConnection.getHeaderFields(); 
    List<String> values = headers.get("Set-Cookie"); 
    String cookieValue = null; 
    for (java.util.Iterator<String> iter = values.iterator(); iter.hasNext(); ) {
         String v = iter.next(); 
         if (cookieValue == null)
             cookieValue = v;
         else
             cookieValue = cookieValue + ";" + v;
    }

    return new Login(cookieValue, response);
}

Наиболее типичное исключение, которое я получаю:

java.io.IOException: сервер вернул код ответа HTTP: 504 для URL: http://www.reddit.com/api/login/kagnito/ на sun.net.www.protocol.http.HttpURLConnection.getInputStream (Неизвестный источник)

Но я также получил много сообщений с «неверным паролем».

Как я могу решить это?Занимался этим часами!

Кстати.Вот что я с трудом понимаю: https://github.com/reddit/reddit/wiki/API%3A-login Я не уверен, как это ЗАПИСАТЬ?Это должно идти в шапку, или?Я не очень знаком с протоколом HTTP.(Отсюда мой проект - я учусь)

1 Ответ

10 голосов
/ 14 ноября 2011

Если не вдаваться в подробности о том, почему все остальное может не работать, есть проблема в том, что вы:

  • Использование URLEncoder для кодирования ваших данных поста: ваши данные поста не собираются в URL, поэтому не кодируйте его.

  • Вы не устанавливаете заголовок Content-Length.

Вот что вам нужно для начала:

public static Login POST(URL url, String user, String pw) throws IOException
{

    String data=  "api_type=json&user=" + user +"&passwd="+pw;
    HttpURLConnection ycConnection = null;
    ycConnection = (HttpURLConnection) url.openConnection();
    ycConnection.setRequestMethod("POST");
    ycConnection.setDoOutput(true);
    ycConnection.setUseCaches (false);
    ycConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
    ycConnection.setRequestProperty("Content-Length", data.length());

    PrintWriter out = new PrintWriter(ycConnection.getOutputStream());


    out.print(data.getBytes());
    out.close();

    BufferedReader in = new BufferedReader(new InputStreamReader(ycConnection.getInputStream()));
    String response = in.readLine();

    Map<String, List<String>> headers = ycConnection.getHeaderFields(); 
    List<String> values = headers.get("Set-Cookie"); 
    String cookieValue = null; 
    for (java.util.Iterator<String> iter = values.iterator(); iter.hasNext(); ) {
         String v = iter.next(); 
         if (cookieValue == null)
             cookieValue = v;
         else
             cookieValue = cookieValue + ";" + v;
    }

    return new Login(cookieValue, response);
}

При работе с такими API вы должны обязательно установить Fiddler , который является отладчиком HTTP. Вы бы сразу увидели проблему, так как ваши данные поста не будут похожи на пример.

UPDATE:

Вот небольшой код, который я только что добавил в тест, и он отлично меня аутентифицировал (очевидно, измените myusername и mypassword на ваш (не забудьте изменить его и в URL):

    @Test
    public void someTest() throws IOException
    {
        URL u = new URL( "https://ssl.reddit.com/api/login/myusername" );
        login( u, "myusername", "mypassword" );
    }

    public static void login( URL url, String user, String pw ) throws IOException
    {

        String data = "api_type=json&user=" + user + "&passwd=" + pw;
        HttpURLConnection ycConnection = null;
        ycConnection = ( HttpURLConnection ) url.openConnection();
        ycConnection.setRequestMethod( "POST" );
        ycConnection.setDoOutput( true );
        ycConnection.setUseCaches( false );
        ycConnection.setRequestProperty( "Content-Type",
            "application/x-www-form-urlencoded; charset=UTF-8" );
        ycConnection.setRequestProperty( "Content-Length", String.valueOf( data.length() ) );

        DataOutputStream wr = new DataOutputStream(
            ycConnection.getOutputStream() );
        wr.writeBytes( data );
        wr.flush();
        wr.close();
        InputStream is = ycConnection.getInputStream();
        BufferedReader rd = new BufferedReader( new InputStreamReader( is ) );
        String line;
        StringBuffer response = new StringBuffer();
        while ( ( line = rd.readLine() ) != null )
        {
            response.append( line );
            response.append( '\r' );
        }
        for ( Entry< String, List< String >> r : ycConnection.getHeaderFields().entrySet() )
        {
            System.out.println( r.getKey() + ": " + r.getValue() );
        }
        rd.close();
        System.out.println( response.toString() );
    }
...