我正在编写一个接收http请求的服务器(只有GET方法作为学校简化的一部分)
我使用Socket
类来获取连接
然后我使用InputStream
以及Scanner
来读取http请求。
然而,当我使用hasNext()
逐行阅读http请求标题时。该程序挂起hasNext()
,等待更多输入,即使它消耗了所有行。
以下是我的readRequest
方法:
public void readRequest(Socket client) throws BadRequestException {
StringBuilder builder = new StringBuilder();
try {
Scanner sc = new Scanner(client.getInputStream());
sc.useDelimiter("\\r\\n");
while(sc.hasNext()){
builder.append(sc.next());
builder.append("\n");
}
parseRequestFromClient(builder.toString());
} catch (IOException e) {
throw new BadRequestException(e.getMessage());
}
答案 0 :(得分:0)
您面临此问题,因为hasNext
会在场景后面读取源,以检查是否有另一个匹配的令牌,直到源到达终点,方法是返回-1
,这不是您的情况。< / p>
这里提醒的是方法hasNext
的Javadoc:
如果此扫描器的输入中有另一个标记,则返回true。这个 方法可能会在等待输入时阻止进行扫描。扫描仪没有 超越任何输入。
你应该避免重新发明方向盘并使用一个能够为你做到的库,比如DavidWebb和其他许多人。
答案 1 :(得分:0)
根据rfc 7230(已废弃2616)从套接字读取字节。
Http请求必须使用7位usascii进行编码。 除了0x0a和0x0d之外,位7设置或小于0x20的任何字节都应该导致400错误请求。
读取直到0x0d 0x0a 0x0d 0x0a序列。
之后第一行是由0x0d 0x0a分隔的请求行,其余是标题行。
将请求行拆分为0x20,它应该正好返回3个部分。 其他任何事情都意味着某人正在攻击你的服务器,发送400状态。
标题应该拼接“:”恰好给出2个部分。其他任何东西发送400状态。 修剪(headerkey)!= headerkey 400状态。
只有在此之后,您才可以开始urldecode请求行[2]和标题值。
重复标头密钥? 400状态。 重复的请求参数? 400状态。
执行任何其他操作将导致服务器比已知的请求参与者和/或标题走私可以破解。
只有通过解释usascii 7位,你才能免受utf8黑客攻击 0x0a在usascii 7位中只有一个表示。但在utf8中有几个 0x0a 0x00a 0x000a 0x0000a 0x00000a 0x00000a 0x0000000a是一样的!
在进行任何编程之前阅读rfc 7230-7235!使你的服务器很难破解。