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
相关产品推荐
相关产品推荐

