You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android端HTTP GET请求被识别为POST的问题求助

GET请求被强制转为POST的问题解决

问题现象

我独立实现了无框架的前后端应用,从Android设备向笔记本上的服务器发送HTTP GET请求时,尽管通过setRequestMethod("GET")显式指定了请求方法,但服务器识别到的请求以及Wireshark抓包结果均显示为POST请求。

相关代码

Android端HTTP工具类

public class ClientHttpUtils {
    private final static Gson GSON = GsonUtils.getInstance();
    private static final ExecutorService executorService = Executors.newFixedThreadPool(4);

    public static <T> void get(
            String path,
            Map<String, String> query,
            Class<T> contentType,
            RequestErrorCallback onError,
            RequestSuccessCallback<T> onSuccess
    ) {
       execute("GET", path, null, query, null, contentType, onError, onSuccess);
    }

    private static <T> void execute(
            String method,
            String path,
            Serializable data,
            Map<String, String> query,
            Headers headers,
            Class<T> contentType,
            RequestErrorCallback onError,
            RequestSuccessCallback<T> onSuccess
    ) {
        executorService.submit(() -> {
            try {
                ResponseModel<T> responseModel = executeRequest(method, path, data, query, headers, contentType);
                if (responseModel != null) {
                    onSuccess.onRequestSuccess(responseModel);

                } else {
                    onError.onRequestError(new Exception("Request failed"));
                }

            } catch (Exception e) {
                onError.onRequestError(e);
            }
        });
    }

    private static <T> ResponseModel<T> executeRequest(
            String method,
            String path,
            Serializable data,
            Map<String, String> query,
            Headers headers,
            Class<T> contentType
    ) throws IOException {

        ResponseModel<T> responseModel = null;

        URL url = new URL(API.BASE_URL + path + mapToQuery(query));

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(method);
        conn.setDoOutput(true);

        if(headers != null) {
            for (String header: headers.keySet()){
                conn.setRequestProperty(header, String.join(",", headers.get(header)));
            }
        }

        if (data != null && method.equals("POST")) {
            byte[] bytes = SerializationUtils.serialize(data);
            conn.setRequestProperty("Content-Type", "application/octet-stream");
            conn.setRequestProperty("Content-Length", String.valueOf(bytes.length));
            conn.getOutputStream().write(bytes);
        } else {
            conn.setRequestProperty("Content-Type", "application/json");
        }

        if(conn.getResponseCode() == StatusCode.SUCCESS){
            responseModel = GSON.fromJson(
                    new InputStreamReader(conn.getInputStream()),
                    TypeToken.getParameterized(ResponseModel.class, contentType).getType());
        }
        else {
            responseModel = GSON.fromJson(
                    new InputStreamReader(conn.getErrorStream()),
                    TypeToken.getParameterized(ResponseModel.class, contentType).getType());
        }

        return responseModel;
    }
    private static String mapToQuery(Map<String, String> query) {
        StringBuilder queryStr = new StringBuilder();

        if (query != null) {
            queryStr = new StringBuilder("?");
            for (Map.Entry<String, String> entry : query.entrySet()) {
                String entity = entry.getValue();
                try {
                    entity = URLEncoder.encode(entity, StandardCharsets.UTF_8.toString());
                } catch (Exception ignore) {
                }

                queryStr.append(entry.getKey()).append("=").append(entity).append("&");
            }
            queryStr = new StringBuilder(queryStr.substring(0, queryStr.length() - 1));
        }

        return queryStr.toString();
    }
}

ResponseModel类

public class ResponseModel<T> {

    private final int status;
    private final boolean success;
    private final String message;
    private final T content;

    public ResponseModel(int status, boolean success, String message, T content) {
        this.status = status;
        this.success = success;
        this.message = message;
        this.content = content;
    }

    public boolean isSuccess() {
        return success;
    }
    public int getStatus() {
        return status;
    }

    public String getMessage() {
        return message;
    }

    public T get() {
        return content;
    }
}

服务器初始化代码

httpServer = HttpServer.create(new InetSocketAddress("192.168.1.X",API.PORT), 0);

已尝试的无效操作

  • 为请求URI添加末尾斜杠(如将/auth/sign-in?username=...改为/auth/sign-in/?username=...)
  • 查找HttpServer是否有类似allowNullPathInfo()的配置项,未找到相关设置

问题根源与解决方案

问题根源

问题出在executeRequest方法中的这一行:

conn.setDoOutput(true);

HttpURLConnection的setDoOutput(true)方法会强制将请求方法切换为POST,因为该方法表示需要向服务器写入请求体,而GET请求按HTTP规范不应包含请求体。即使你没有实际写入任何数据,只要设置了这个属性,连接就会自动修改请求方法。

解决方案

修改executeRequest方法,仅在POST请求时设置setDoOutput(true),GET请求保持默认(或显式设置为false):

// 替换原有的conn.setDoOutput(true);
if (method.equals("POST")) {
    conn.setDoOutput(true);
}
// GET请求无需设置,默认就是false

同时,GET请求分支中设置Content-Type为application/json是多余的,因为GET请求没有请求体,可以删除该分支的相关代码:

// 原代码
// } else {
//     conn.setRequestProperty("Content-Type", "application/json");
// }

// 修改后仅保留POST请求的处理逻辑
if (data != null && method.equals("POST")) {
    byte[] bytes = SerializationUtils.serialize(data);
    conn.setRequestProperty("Content-Type", "application/octet-stream");
    conn.setRequestProperty("Content-Length", String.valueOf(bytes.length));
    conn.getOutputStream().write(bytes);
}

修改后,GET请求会保持正确的请求方法,不会被自动转为POST。

内容的提问来源于stack exchange,提问作者Farbod Bijary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 07:32:02