using System.ComponentModel;
using NewLife;
using NewLife.Data;
using NewLife.Http;
using Xunit;
namespace XUnitTest.Http;
/// <summary>HTTP å¤´éƒ¨è¡Œçš„ä¸¥æ ¼æ ¡éªŒæµ‹è¯•ï¼ˆè¯·æ±‚æ‹’ç»ã€å“应宽容)</summary>
/// <remarks>
/// <para>RFC 7230 §3.2.4:请求ä¸å‡ºçŽ°ã€Œå—æ®µå与冒å·ä¹‹é—´çš„ç©ºç™½ã€æˆ–「以空白开头的ç»è¡ŒæŠ˜å (obs-fold)ã€ï¼Œ
/// æœåŠ¡ç«¯å¿…é¡»æ‹’ç»æˆ–替æ¢ä¸ºç©ºæ ¼ï¼›è€Œå¯¹å“应,客户端必须替æ¢ã€ä¸å¾—æ‹’ç»ã€‚</para>
/// <para>è‹¥ä¸æ‹’ç»è¯·æ±‚侧的畸形行,本端与å‰ç½®ä»£ç†ä¼šå¯¹åŒä¸€æ®µå—节得出ä¸åŒé•¿åº¦ç†è§£ï¼Œæž„æˆè¯·æ±‚èµ°ç§é¢ï¼š
/// ä»£ç†æŒ‰ OWS(å«åˆ¶è¡¨ç¬¦ï¼‰å‰¥åŽ»ç©ºç™½åŽè®¤å‡º <c>Content-Length</c>ï¼Œæœ¬ç«¯å´æŠŠå®ƒå½“æˆæœªçŸ¥å¤´éƒ¨ã€‚</para>
/// </remarks>
public class HttpHeaderStrictTests
{
[Fact]
[DisplayName("HTTP请求_å—æ®µåå«åˆ¶è¡¨ç¬¦_è§£æžå¤±è´¥")]
public void Request_TabBeforeColon_Rejected()
{
// å—æ®µå与冒å·ä¹‹é—´çš„制表符:Trim(' ') åŽ»ä¸æŽ‰å®ƒï¼Œæ—§å®žçŽ°æŠŠåå—è§£æžæˆã€ŒContent-Length\tã€è€Œè®¤ä¸å‡ºé•¿åº¦å¤´
var req = new HttpRequest();
var data = "POST /x HTTP/1.1\r\nHost: a\r\nContent-Length\t: 5\r\n\r\nHELLO".GetBytes();
Assert.False(req.Parse(new ArrayPacket(data)));
}
[Fact]
[DisplayName("HTTP请求_å—æ®µååŽæœ‰ç©ºæ ¼å†æŽ¥å†’å·_è§£æžå¤±è´¥")]
public void Request_SpaceBeforeColon_Rejected()
{
// å—æ®µå与冒å·ä¹‹é—´çš„ç©ºæ ¼ä¼šè¢« Trim(' ') 抹掉,解æžç»“果与å‰ç½®ä»£ç†ã€Œæ‹’ç»è¯¥è¯·æ±‚ã€çš„ç†è§£ä¸ä¸€è‡´
var req = new HttpRequest();
var data = "POST /x HTTP/1.1\r\nHost: a\r\nContent-Length : 5\r\n\r\nHELLO".GetBytes();
Assert.False(req.Parse(new ArrayPacket(data)));
}
[Fact]
[DisplayName("HTTP请求_头部ç»è¡ŒæŠ˜å _è§£æžå¤±è´¥")]
public void Request_ObsFold_Rejected()
{
// ç»è¡ŒæŠ˜å :Trim å‰å¯¼ç©ºæ ¼åŽåå—æ£å¥½å‘½ä¸ Content-Lengthï¼Œæœ¬ç«¯ä¼šæ®æ¤ç‰å¾…实体,
// 而å‰ç½®ä»£ç†æŠŠè¯¥è¡Œè§†ä¸ºä¸Šä¸€å¤´éƒ¨çš„ç»è¡Œï¼ˆä¸äº§ç”Ÿé•¿åº¦å¤´ï¼‰
var req = new HttpRequest();
var data = "GET /x HTTP/1.1\r\nHost: a\r\n Content-Length: 5\r\n\r\n".GetBytes();
Assert.False(req.Parse(new ArrayPacket(data)));
}
[Fact]
[DisplayName("HTTP请求_冒å·åŽåˆ¶è¡¨ç¬¦_仿Œ‰é•¿åº¦å¤´è¯†åˆ«")]
public void Request_TabAfterColon_Accepted()
{
// 冒å·ä¹‹åŽçš„空白属于 RFC å…许的 OWS(SP/HTAB),ä¸å¾—误伤:值侧去空白åŽåº”æ£å¸¸è¯†åˆ«é•¿åº¦
var req = new HttpRequest();
var data = "POST /x HTTP/1.1\r\nHost: a\r\nContent-Length:\t5\r\n\r\nHELLO".GetBytes();
Assert.True(req.Parse(new ArrayPacket(data)));
Assert.Equal(5, req.ContentLength);
Assert.False(req.InvalidContentLength);
Assert.Equal("HELLO", req.Body.ToStr());
}
[Fact]
[DisplayName("HTTP请求_常规头部_æ£å¸¸è§£æž")]
public void Request_NormalHeader_Parsed()
{
var req = new HttpRequest();
var data = "POST /x HTTP/1.1\r\nHost: example.com\r\nContent-Type: text/plain\r\nContent-Length: 3\r\n\r\nabc".GetBytes();
Assert.True(req.Parse(new ArrayPacket(data)));
Assert.Equal("POST", req.Method);
Assert.Equal("example.com", req.Headers["Host"]);
Assert.Equal("text/plain", req.ContentType);
Assert.Equal(3, req.ContentLength);
Assert.Equal("abc", req.Body.ToStr());
}
[Fact]
[DisplayName("HTTPå“应_åŒç±»ç•¸å½¢è¡Œ_ä¿æŒå®½å®¹ä¸å½±å“客户端解æž")]
public void Response_MalformedHeader_Tolerated()
{
// å“应侧ä¸å¼ºåˆ¶æ‹’ç»ï¼šRFC è¦æ±‚客户端替æ¢è€Œéžæ‹’ç»ï¼Œé¿å…è§£æžä¸äº†åކ岿œåС噍
var res = new HttpResponse();
var data = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\nX-a: 1\r\n X-b: 2\r\n\r\n".GetBytes();
Assert.True(res.Parse(new ArrayPacket(data)));
Assert.Equal("1", res.Headers["X-a"]);
}
}
|