Error parsing HTTP request header 控制台报错分析与解决

本文详细解析了Tomcat中出现的HTTP请求头解析错误,主要原因是header缓冲区大小不足或URL中包含非法字符。文章提供了两种解决方案,一是调整Tomcat配置文件server.xml中的maxHttpHeaderSize参数;二是对URL中的不安全字符进行转义。

控制台报错信息:

 org.apache.coyote.http11.AbstractHttp11Processor process
信息: Error parsing HTTP request header
 Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
	at org.apache.coyote.http11.InternalInputBuffer.parseRequestLine(InternalInputBuffer.java:194)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1050)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:744)

  解决方案及原因分析:

一、原因是Tomcat的header缓冲区大小不够,只需要在server.xml中增加maxHttpHeaderSize,设置如

<Connector connectionTimeout="20000" maxHttpHeaderSize="8999" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

二、使用了不安全字符,他们直接放在Url中的时候,可能会引起解析程序的歧义。如

{ } | \ ^ [ ] ` ~ % # 等

如果要在url里使用不安全字符,就需要使用转义。

转载于:https://www.cnblogs.com/ladyM/p/10532886.html

仿照# -*- coding: utf-8 -*- import socket import ssl import time import os import logging from urllib.parse import urlparse def send_file(url: str, mac_address: str, file_path: str, chunk_size: int = 8192): """ Send file to server, placing file content in HTTP request body :param url: Server URL (https://host:port/path) :param mac_address: Device MAC address (format: A1:B2:C3:D4:E5:F6) :param file_path: File path to send :param chunk_size: Chunk size for transfer (default: 8KB) :return: Returns True on success, False on failure """ # Parse URL try: parsed_url = urlparse(url) host = parsed_url.hostname port = parsed_url.port or 443 # Default HTTPS port path = parsed_url.path if not host: raise ValueError("Missing host in URL") except Exception as e: logging.error(f"URL parsing failed: {e}") return False # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s', handlers=[logging.FileHandler('transfer.log'), logging.StreamHandler()] ) # 1. Prepare file information try: file_size = os.path.getsize(file_path) filename = os.path.basename(file_path) logging.info(f"Preparing to send file to {path}: {file_path} ({file_size} bytes)") except Exception as e: logging.error(f"File loading failed: {e}") return False # 2. Create SSL connection (with retry mechanism) MAX_RETRIES = 3 RETRY_DELAY = 2 # seconds ssl_sock = None for attempt in range(MAX_RETRIES): try: context = ssl.create_default_context() context.check_hostname = False # Can disable hostname verification in test environments context.verify_mode = ssl.CERT_NONE # Can disable certificate verification in test environments # context.load_verify_locations(cafile="/path/to/ca_cert.pem") sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(120) # Set longer timeout ssl_sock = context.wrap_socket(sock, server_hostname=host) ssl_sock.connect((host, port)) logging.info(f"SSL connection established to {host}:{port}") break except Exception as e: if attempt < MAX_RETRIES - 1: logging.warning(f"SSL connection failed ({attempt+1}/{MAX_RETRIES}): {e}, retrying in {RETRY_DELAY} seconds...") time.sleep(RETRY_DELAY) else: logging.error(f"Maximum retries reached: {e}") return False # 3. Build and send HTTP request headers try: # Construct HTTP request headers headers = [ f"POST {path} HTTP/1.1", f"Host: {host}", "Cache-Control: no-cache", "Connection: keep-alive", f"Device-Mac: {mac_address}", # MAC address header required by server f"FileName: {filename}", # Filename header required by server f"Content-Length: {file_size}", # Key: content length "\r\n" # Empty line ends the headers ] header_str = "\r\n".join(headers) logging.debug(f"Request headers:\n{header_str}") ssl_sock.sendall(header_str.encode('utf-8')) except Exception as e: logging.error(f"Request header send error: {e}") if ssl_sock: ssl_sock.close() return False # 4. Send file content (request body) bytes_sent = 0 start_time = time.time() last_progress_update = start_time try: with open(file_path, 'rb') as f: while bytes_sent < file_size: # Read and send data chunk chunk = f.read(chunk_size) if not chunk: break ssl_sock.sendall(chunk) bytes_sent += len(chunk) # Smart progress update (maximum once per second) current_time = time.time() if current_time - last_progress_update > 1.0: progress = bytes_sent / file_size * 100 elapsed = current_time - start_time speed = bytes_sent / (elapsed * 1024) # KB/s logging.info( f"Sending: {bytes_sent}/{file_size} bytes " f"({progress:.1f}%), Speed: {speed:.2f} KB/s" ) last_progress_update = current_time logging.info(f"File transfer completed: {bytes_sent}/{file_size} bytes") except Exception as e: logging.error(f"Transfer interrupted: {e}") if ssl_sock: ssl_sock.close() return False # 5. Receive server response try: response = b"" while True: chunk = ssl_sock.recv(1024) if not chunk: break response += chunk logging.info(f"Server response: {response.decode('utf-8', errors='ignore')}") except Exception as e: logging.error(f"Response receive error: {e}") # 6. Close connection and calculate performance ssl_sock.close() elapsed = time.time() - start_time if bytes_sent == file_size: speed = file_size / (elapsed * 1024) # KB/s logging.info(f"Transfer successful! Time: {elapsed:.2f} seconds, Speed: {speed:.2f} KB/s") return True logging.warning(f"Transfer incomplete: {bytes_sent}/{file_size} bytes") return False if __name__ == "__main__": # Configure server information SERVER_URL = "https://192.168.137.93:21443/log/file_log_set" # Ensure path matches server TEST_MAC = "A1:B2:C3:D4:E5:F6" # MAC address format TEST_FILE = "test_log2.txt" # File to send print("="*50) send_file(SERVER_URL, TEST_MAC, TEST_FILE) print("="*50) 改写代码:import requests def get_device_logs(): """ Client function to retrieve device logs (fixed MAC and disabled SSL verification) """ # Target URL url = "https://192.168.137.93:21443/log/file_log_get" # Fixed MAC address value fixed_mac = "A1:B2:C3:D4:E5:F6" try: # Send GET request response = requests.get( url, params={"Device-Mac": fixed_mac}, verify=False, # Disable SSL verification timeout=10 ) # Check HTTP status code if response.status_code == 200: print("Log retrieval successful! Content:\n") print(response.text) else: print(f"Request failed! Status code: {response.status_code}") print(f"Request URL: {response.url}") print(f"Error details: {response.text[:200]}" if response.text else "No error details") # Attempt to get server debug information server_error = response.headers.get('X-Error-Detail', "N/A") print(f"Server error: {server_error}") except requests.exceptions.SSLError: print("SSL certificate verification failed! (Should not occur with verify=False)") except requests.exceptions.ConnectionError: print("Connection to server failed. Check network or server status") except requests.exceptions.Timeout: print("Request timeout. Check network connection or retry") except Exception as e: print(f"Unknown error: {str(e)}") if __name__ == "__main__": # Execute log retrieval with fixed parameters get_device_logs()
最新发布
10-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值