当前位置: 首页 > 知识库问答 >
问题:

如何使用连接以与阿帕奇客户端库相同的方式发出 POST 请求

岳志义
2023-03-14

我正在尝试向一个网站发送帖子请求。作为对POST请求的响应,我希望得到一些JSON数据。

使用Apache的HttpClient库,我可以毫无问题地做到这一点。响应数据是JSON,所以我只是解析它。

package com.mydomain.myapp;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class MyApp {

    private static String extract(String patternString, String target) {

        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(target);
        matcher.find();
        return matcher.group(1);
    }

    private String getResponse(InputStream stream) throws Exception {

        BufferedReader in = new BufferedReader(new InputStreamReader(stream));
        String inputLine;
        StringBuffer responseStringBuffer = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            responseStringBuffer.append(inputLine);
        }
        in.close();
        return responseStringBuffer.toString();
    }

    private final static String BASE_URL = "https://www.volkswagen-car-net.com";
    private final static String BASE_GUEST_URL = "/portal/en_GB/web/guest/home";

    private void run() throws Exception {

        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(BASE_URL + BASE_GUEST_URL);
        CloseableHttpResponse getResponse = client.execute(httpGet);
        HttpEntity responseEntity = getResponse.getEntity();
        String data = getResponse(responseEntity.getContent());
        EntityUtils.consume(responseEntity);

        String csrf = extract("<meta name=\"_csrf\" content=\"(.*)\"/>", data);
        System.out.println(csrf);

        HttpPost post = new HttpPost(BASE_URL + "/portal/web/guest/home/-/csrftokenhandling/get-login-url");
        post.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        post.setHeader("User-Agent'", "Mozilla/5.0 (Linux; Android 6.0.1; D5803 Build/23.5.A.1.291; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.111 Mobile Safari/537.36");
        post.setHeader("Referer", BASE_URL + "/portal");
        post.setHeader("X-CSRF-Token", csrf);

        CloseableHttpResponse postResponse = client.execute(post);
        HttpEntity postResponseEntity = postResponse.getEntity();
        String postData = getResponse(postResponseEntity.getContent());
        System.out.println(postData);
        EntityUtils.consume(postResponseEntity);
        postResponse.close();
    }

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

        MyApp myApp = new MyApp();
        myApp.run();
    }
}

但是我不能在我的项目中使用HttpClient库。我需要能够用“just”HttpURLConnection做同样的事情。

但是HttpClient库有一些我无法理解的魔力。因为使用HttpURLConnection对我的POST请求的响应只是重定向到不同的网页。

有人能给我指出正确的方向吗?

以下是我当前的HttpURLConnection尝试:

package com.mydomain.myapp;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MyApp {

    private static String extract(String patternString, String target) {

        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(target);
        matcher.find();
        return matcher.group(1);
    }

    private final static String BASE_URL = "https://www.volkswagen-car-net.com";
    private final static String BASE_GUEST_URL = "/portal/en_GB/web/guest/home";

    private String getResponse(InputStream stream) throws Exception {

        BufferedReader in = new BufferedReader(new InputStreamReader(stream));
        String inputLine;
        StringBuffer responseStringBuffer = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            responseStringBuffer.append(inputLine);
        }
        in.close();
        return responseStringBuffer.toString();
    }

    private String getResponse(HttpURLConnection connection) throws Exception {
        return getResponse(connection.getInputStream());
    }

    private void run() throws Exception {

        HttpURLConnection getConnection1;
        URL url = new URL(BASE_URL + BASE_GUEST_URL);
        getConnection1 = (HttpURLConnection) url.openConnection();
        getConnection1.setRequestMethod("GET");
        if (getConnection1.getResponseCode() != HttpURLConnection.HTTP_OK) {
            throw new Exception("Request failed");
        }

        String response = getResponse(getConnection1);
        getConnection1.disconnect();

        String csrf = extract("<meta name=\"_csrf\" content=\"(.*)\"/>", response);
        System.out.println(csrf);

        HttpURLConnection postRequest;
        URL url2 = new URL(BASE_URL + "/portal/web/guest/home/-/csrftokenhandling/get-login-url");
        postRequest = (HttpURLConnection) url2.openConnection();
        postRequest.setDoOutput(true);
        postRequest.setRequestMethod("POST");
        postRequest.setInstanceFollowRedirects(false);

        postRequest.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        postRequest.setRequestProperty("User-Agent'", "Mozilla/5.0 (Linux; Android 6.0.1; D5803 Build/23.5.A.1.291; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.111 Mobile Safari/537.36");
        postRequest.setRequestProperty("Referer", BASE_URL + "/portal");
        postRequest.setRequestProperty("X-CSRF-Token", csrf);

        postRequest.disconnect();
    }

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

        MyApp myApp = new MyApp();
        myApp.run();
    }
}

共有1个答案

宗增
2023-03-14

由一个伟大的程序员资源,例如MKYong(你知道你以前遇到过他的网站;-)),我会仔细研究它的要点,以防链接出现故障。

要点:

HttpURLConnection的跟随重定向只是一个指示器,实际上它不会帮助你做“真实”的超文本传输协议重定向,你仍然需要手动处理它。
如果服务器从原始URL重定向到另一个URL,响应代码应该是301: Moved Permanally或302:临时重定向。您可以通过读取HTTP响应头的“位置”头来获取新的重定向url。

例如,访问正常的HTTP twitter网站-http://www.twitter.com,它将自动重定向到HTTPS twitter网站-https://www.twitter.com.

示例代码

package com.mkyong.http;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpRedirectExample {

  public static void main(String[] args) {

    try {

    String url = "http://www.twitter.com";

    URL obj = new URL(url);
    HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
    conn.setReadTimeout(5000);
    conn.addRequestProperty("Accept-Language", "en-US,en;q=0.8");
    conn.addRequestProperty("User-Agent", "Mozilla");
    conn.addRequestProperty("Referer", "google.com");

    System.out.println("Request URL ... " + url);

    boolean redirect = false;

    // normally, 3xx is redirect
    int status = conn.getResponseCode();
    if (status != HttpURLConnection.HTTP_OK) {
        if (status == HttpURLConnection.HTTP_MOVED_TEMP
            || status == HttpURLConnection.HTTP_MOVED_PERM
                || status == HttpURLConnection.HTTP_SEE_OTHER)
        redirect = true;
    }

    System.out.println("Response Code ... " + status);

    if (redirect) {

        // get redirect url from "location" header field
        String newUrl = conn.getHeaderField("Location");

        // get the cookie if need, for login
        String cookies = conn.getHeaderField("Set-Cookie");

        // open the new connnection again
        conn = (HttpURLConnection) new URL(newUrl).openConnection();
        conn.setRequestProperty("Cookie", cookies);
        conn.addRequestProperty("Accept-Language", "en-US,en;q=0.8");
        conn.addRequestProperty("User-Agent", "Mozilla");
        conn.addRequestProperty("Referer", "google.com");

        System.out.println("Redirect to URL : " + newUrl);

    }

    BufferedReader in = new BufferedReader(
                              new InputStreamReader(conn.getInputStream()));
    String inputLine;
    StringBuffer html = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        html.append(inputLine);
    }
    in.close();

    System.out.println("URL Content... \n" + html.toString());
    System.out.println("Done");

    } catch (Exception e) {
    e.printStackTrace();
    }

  }

}
 类似资料:
  • 我正在尝试使用Apache HTTPClient 4.5.1来执行一些rest请求。不幸的是,每一秒的请求都会以“java.net.SocketTimeoutException:Read timed out”结尾(如果没有设置套接字超时,则永远挂起)。 我正在这样构建我的客户: 之后,我像这样执行我的请求(在同一个 Http 客户端实例上): 如果我开始为每个请求使用一个新的HttpClient实

  • Apache Kafka:分布式消息传递系统 Apache Storm:实时消息处理 我们如何在实时数据管道中使用这两种技术来处理事件数据? 在实时数据管道方面,我觉得两者做的工作是一样的。如何在数据管道上同时使用这两种技术?

  • 我正在玩ApacheCamel,在从“琐碎的示例”阶段过渡到“但有这些恼人的细节”阶段时遇到了一些问题。至关重要的是,如何进入并显式修改endpoint。 在这种情况下,我需要为超文本传输协议客户端设置一个auth cookie。我有一个cookie存储对象,但不知道如何强制客户端使用它。我试过使用,但没有公开cookie存储,而且它似乎也没有被调用。 我现在的代码: 并由以下人员调用: 知道我如

  • 问题内容: Google Chrome的ADVANCED REST CLIENT插件如何发出跨域POST请求?我以为可能是CORS出现问题,但在任何响应中都看不到“ Access-Control-Allow-Origin”。这是插件的链接: https://chrome.google.com/webstore/detail/hgmloofddffdnphfgcellkdfbfbjeloo/rela

  • 无法连接。无法建立到jdbc的连接:derby://localhost:1527/sample使用组织。阿帕奇。德比。jdbc。ClientDriver(DERBY SQL错误:错误代码:40000,SQLSTATE:XJ040,SQLERRMC:无法使用类加载器sun.misc.Launcher启动数据库'sample'$AppClassLoader@1d44bcfa,有关详细信息,请参见下一个