/
on-line-javalex
/
HW_FORMS
Обзор
Документация
Войти
/
on-line-javalex
/
HW_FORMS
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
HttpRequest.java
276 строк
10 KB
on-line-javalex
upload files
03 мар 2026, 07:47
Верифицирован
03 мар 2026, 07:47
468c7a8
Код
Авторство
О чём код?
package netology; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.commons.fileupload.MultipartStream; import org.apache.commons.fileupload.ParameterParser; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.*; public class HttpRequest { private final String method; private final String path; private final String queryString; private final Map<String, String> headers; private final byte[] body; private final Map<String, List<String>> queryParams; private Map<String, List<String>> postParams; private List<Part> parts; public HttpRequest(String method, String path, String queryString, Map<String, String> headers, byte[] body) { this.method = method; this.path = path; this.queryString = queryString; this.headers = Collections.unmodifiableMap(new HashMap<>(headers)); this.body = body.clone(); this.queryParams = new HashMap<>(); if (queryString != null) { List<NameValuePair> pairs = URLEncodedUtils.parse(queryString, StandardCharsets.UTF_8); for (NameValuePair pair : pairs) { queryParams.computeIfAbsent(pair.getName(), k -> new ArrayList<>()).add(pair.getValue()); } } } public String getMethod() { return method; } public String getPath() { return path; } public String getQueryString() { return queryString; } public Map<String, String> getHeaders() { return headers; } public byte[] getBody() { return body.clone(); } public Map<String, List<String>> getQueryParams() { return Collections.unmodifiableMap(queryParams); } public String getQueryParam(String name) { List<String> values = queryParams.get(name); return (values != null && !values.isEmpty()) ? values.get(0) : null; } public List<String> getQueryParamValues(String name) { return queryParams.getOrDefault(name, Collections.emptyList()); } private void parsePostParams() { if (postParams != null) return; postParams = new HashMap<>(); String contentType = headers.get("content-type"); if (contentType == null || !contentType.startsWith("application/x-www-form-urlencoded")) { return; } if (body.length == 0) return; String bodyString = new String(body, StandardCharsets.UTF_8); List<NameValuePair> pairs = URLEncodedUtils.parse(bodyString, StandardCharsets.UTF_8); for (NameValuePair pair : pairs) { postParams.computeIfAbsent(pair.getName(), k -> new ArrayList<>()).add(pair.getValue()); } } public Map<String, List<String>> getPostParams() { parsePostParams(); return Collections.unmodifiableMap(postParams); } public String getPostParam(String name) { parsePostParams(); List<String> values = postParams.get(name); return (values != null && !values.isEmpty()) ? values.get(0) : null; } public List<String> getPostParamValues(String name) { parsePostParams(); return postParams.getOrDefault(name, Collections.emptyList()); } private void parseMultipart() throws IOException { if (parts != null) return; parts = new ArrayList<>(); String contentType = headers.get("content-type"); if (contentType == null || !contentType.startsWith("multipart/form-data")) { return; } String boundary = extractBoundary(contentType); if (boundary == null) { throw new IOException("Boundary not found in Content-Type: " + contentType); } ByteArrayInputStream input = new ByteArrayInputStream(body); MultipartStream multipartStream = new MultipartStream(input, boundary.getBytes(), 4096, null); boolean nextPart = multipartStream.skipPreamble(); while (nextPart) { String headersString = multipartStream.readHeaders(); Map<String, String> partHeaders = parseHeaders(headersString); String contentDisposition = partHeaders.get("content-disposition"); if (contentDisposition == null) { throw new IOException("Missing Content-Disposition in part"); } String name = extractParameter(contentDisposition, "name"); String filename = extractParameter(contentDisposition, "filename"); String partContentType = partHeaders.get("content-type"); ByteArrayOutputStream partBodyStream = new ByteArrayOutputStream(); multipartStream.readBodyData(partBodyStream); byte[] partBody = partBodyStream.toByteArray(); parts.add(new Part(name, filename, partBody, partContentType, partHeaders)); nextPart = multipartStream.readBoundary(); } } private String extractBoundary(String contentType) { String[] parts = contentType.split(";"); for (String part : parts) { part = part.trim(); if (part.startsWith("boundary=")) { String boundary = part.substring("boundary=".length()); if (boundary.startsWith("\"") && boundary.endsWith("\"")) { boundary = boundary.substring(1, boundary.length() - 1); } return boundary; } } return null; } private Map<String, String> parseHeaders(String headersString) { Map<String, String> result = new HashMap<>(); String[] lines = headersString.split("\r\n"); for (String line : lines) { int colon = line.indexOf(':'); if (colon > 0) { String key = line.substring(0, colon).trim().toLowerCase(); String value = line.substring(colon + 1).trim(); result.put(key, value); } } return result; } private String extractParameter(String header, String paramName) { ParameterParser parser = new ParameterParser(); Map<String, String> params = parser.parse(header, ';'); return params.get(paramName); } public List<Part> getParts() throws IOException { parseMultipart(); return Collections.unmodifiableList(parts); } public Part getPart(String name) throws IOException { parseMultipart(); for (Part part : parts) { if (part.getName().equals(name)) { return part; } } return null; } public static HttpRequest fromInputStream(InputStream inputStream) throws IOException { ByteArrayOutputStream headerStream = new ByteArrayOutputStream(); int prevChar = -1; int currentChar; boolean headersEnded = false; while ((currentChar = inputStream.read()) != -1) { headerStream.write(currentChar); if (prevChar == '\r' && currentChar == '\n') { int nextChar = inputStream.read(); if (nextChar == -1) break; headerStream.write(nextChar); if (nextChar == '\r') { int nextNextChar = inputStream.read(); if (nextNextChar == -1) break; headerStream.write(nextNextChar); if (nextNextChar == '\n') { headersEnded = true; break; } } } prevChar = currentChar; } if (!headersEnded) { throw new IOException("Malformed HTTP request: headers not terminated properly"); } byte[] headerBytes = headerStream.toByteArray(); String headerString = new String(headerBytes, StandardCharsets.ISO_8859_1); String[] headerLines = headerString.split("\r\n"); if (headerLines.length == 0) { throw new IOException("Empty request"); } String requestLine = headerLines[0]; String[] parts = requestLine.split(" "); if (parts.length != 3) { throw new IOException("Invalid request line: " + requestLine); } String method = parts[0]; String fullPath = parts[1]; String path; String queryString; int queryIdx = fullPath.indexOf('?'); if (queryIdx >= 0) { path = fullPath.substring(0, queryIdx); queryString = fullPath.substring(queryIdx + 1); } else { path = fullPath; queryString = null; } Map<String, String> headers = new HashMap<>(); for (int i = 1; i < headerLines.length; i++) { String line = headerLines[i]; if (line.isEmpty()) continue; int colon = line.indexOf(':'); if (colon > 0) { String key = line.substring(0, colon).trim().toLowerCase(); String value = line.substring(colon + 1).trim(); headers.put(key, value); } } int contentLength = 0; String contentLengthStr = headers.get("content-length"); if (contentLengthStr != null) { try { contentLength = Integer.parseInt(contentLengthStr); } catch (NumberFormatException e) { } } byte[] body; if (contentLength > 0) { body = new byte[contentLength]; int read = 0; while (read < contentLength) { int result = inputStream.read(body, read, contentLength - read); if (result == -1) { throw new IOException("Premature EOF while reading body"); } read += result; } } else { body = new byte[0]; } return new HttpRequest(method, path, queryString, headers, body); } }