2009-08-25 4 views
1

우리는 C#에서 Google의 응용 프로그램을 호스팅하는 IIS7을 사용하는 HTTP 위에있는 포괄적 인 통합 테스트 프레임 워크를 구축하고 있습니다.C#에서 HTTP 용 잘못된 콘텐츠 길이 헤더 시뮬레이션

통합 테스트의 일환으로 클라이언트가 실제로보다 큰 본문 크기를 나타내는 HTTP 헤더를 보내면 발생하는 EndOfStreamExceptions ("스트림 끝 부분을 읽을 수 없습니다")이 발생하는 들어오는 요청을 테스트하려고합니다. 몸의 일부로 전송됩니다. 우리는 이러한 종류의 요청을 시뮬레이션해야하므로이 조건에 대한 오류 복구 코드를 테스트하려고합니다.

.NET Fx 기반 소켓 라이브러리 또는 개발자가 특별히 이러한 조건을 시뮬레이션하여 통합 테스트 스위트에 추가 할 수있는 사용자 지정 HttpWebRequest 대체품을 찾고 있습니다. 누구든지 그러한 라이브러리를 알고 있습니까? 스크립트 가능한 솔루션도 잘 작동합니다.

답변

4

GetRequestStream (또는 BeginGetRequestStream)을 호출하기 전에 ContentLength 속성을 설정 한 다음 해당 스트림에 더 적은 바이트를 씁니다. 요청 스트림을받은 후에 ContentLength를 설정하려고하면 ContentLength가 발생합니다. ContentLength를 설정하지 않으면 스트림이 닫힐 때까지 HttpWebRequest가 헤더를 버퍼링하여 적절하게 ContentLength를 설정할 수 있습니다 (또는 SendChunked를 사용할 수 있지만 여기서는 사용할 수 없습니다). 이 것을 최대한 제어하려면 악의적 인 요청을 한두 씩 작성한 다음 서버의 포트 80에 대한 소켓을 열고 TCP 스트림에 요청을 작성한 다음 응답을 읽고 연결을 확인하여 닫혀 있는지 확인하십시오 .

그러나이 테스트가 좋은 생각이라고 생각하지 않습니다. 문제는 다음과 같습니다.

클라이언트가 서버에 요청을 보냅니다. 내용이 100 바이트라고 주장합니다. 그런 다음 90 바이트를 전송 한 다음 전송을 중지하고 연결을 열린 상태로 둡니다. 서버는 90 바이트를 읽은 다음 클라이언트가 100 바이트를 전송한다고 말한 이후로 나머지를 기다립니다. 이제 클라이언트는 두 번째 요청을 보냅니다. 서버가 새로운 요청의 처음 10 바이트를 어떻게 처리합니까?

대답은 서버가 그 바이트가 이전 요청의 일부라고 가정하고이를 처리 한 다음 시작 후 10 바이트가되는 "새로운"요청 읽기를 시작하므로 분명히 잘못된 헤더가 생성됩니다. 서버가 그것을 좋아하지 않으므로 4xx 오류를 보내고 연결을 닫습니다. 연결을 닫는 이유는 데이터가 전송되는 의미와 복구 할 수없는 방법을 알 수 없기 때문입니다. 또한 연결이 닫히는 것은 적절하지 않을 것입니다. 갑자기 두 번째 요청을 제출하는 상대방의 HttpWebRequest (또는 큐에 대기중인 경우 세 번째 또는 네 번째)가 WebException을 throw합니다. 기본 연결이 닫히고 왜 그런지 짐작할 수 있습니다.

동일한 동작으로 인해 Expect 100-continue 헤더로 연결이 닫히고 서 버는 인증이 필요할 때와 같이 100-continue와 4xx를 반환합니다. 요청을 거부하더라도 다음 바이트가 100-continue를 전송하여 해당 바이트를 수신하기로 약속 했으므로 다음 바이트가 동일한 요청의 일부라고 가정해야합니다.요청을 처리하지 못하거나 클라이언트가 요청을 취소하고 새 인증을 제출하려는 경우 (아마도 인증 자격 증명을 사용하여) 연결을 닫고 새 인증서를 열어야합니다.

마지막으로 TCP를 사용하여 네트워크 스트림에서 EndOfStreamException을 테스트하는 것은 전혀 의미가 없습니다. TCP는 스트림의 "끝"을 표시하지 않고 소켓에 기록 된대로 데이터를 계속 전송합니다. 데이터에 대한 "EOF"가 없으며 예상 데이터 양을 알지 못하면 데이터가 모두 전송되었는지 여부를 감지 할 수 없습니다. 연결이 닫히지 않는 한 TCP는 실제로 스트림의 "끝"을 갖지 않습니다.이 경우 스택에서 어디서 작동하는지에 따라 WebException 또는 SocketException이 발생합니다. 프로토콜의 모든 전송 오류는 winsock에서 처리됩니다. 데이터가 더 이상 전송되지 않으면 연결의 한쪽 끝에서 다른 쪽 연결에 키를 보내 결국 연결이 실제로 열려 있는지 그리고 한 호스트가 연결을 끊어 버리지 않았는지 확인합니다. keepalive가 시간 초과되면 연결이 닫히고 다음 번에 연결을 읽으려고 할 때 WebException이 발생할 수 있습니다. 이 모든 것이 어떻게 작동하는지 감안할 때, 나는이 테스트에서 어떤 가치를 얻을 수 있는지 보지 못합니다. 잘못된 요청을 보내고 그에 따라 오류가 처리되고 적절한 4xx 메시지가 클라이언트로 보내지고 연결이 제대로 닫히고 있는지 확인하는 것이 훨씬 낫습니다.

0

나는 이러한 라이브러리에 대해 잘 모르지만, 코딩 측면에서 보면 수신 측에서는 매우 간단 할 것 같습니다.

전체 WebRequest를 검색하고 원하는만큼 잘라내어 전달하십시오. 현재 위치에서 잘라내 기보다는이 과정에서 WebRequest의 새로운 복사본을 만들어야 할 수도 있지만 여전히 간단해야합니다.

+0

통합 테스트는 클라이언트를 시뮬레이션합니다. 테스트를 용이하게하기 위해 수신 측을 변경할 수 없습니다. – cfeduke

0

클라이언트의 HttpWebRequest.ContentLength 속성을 데이터의 실제 크기보다 작거나 큰 값으로 설정할 수 없습니까?

0

HTTP 프로토콜을 위반하는 곳에서 이와 같은 것을 시뮬레이션하고 싶다면 직접 코드를 작성해야합니다. HttpWebRequest는 이와 같은 일을 허용하지 않습니다.