Какао: обработка 407 http ответа cfnetwork - PullRequest
2 голосов
/ 15 октября 2011

Я создаю приложение для загрузки. Я столкнулся с проблемой проверки подлинности прокси. Я получаю код ответа 407, т.е. требуется проверка подлинности прокси. У меня есть действительные данные аутентификации прокси.

Ниже приведен код потока:

 1. Create Http request using CFHTTPMessageCreateRequest
 2. Set necessary header field values like Cache-Control, Accept-Ranges, Range & User-Agent  using CFHTTPMessageSetHeaderFieldValue
 3. Create read stream using CFReadStreamCreateForHTTPRequest
 4. Set proxy server URL & port properties on read stream using CFReadStreamSetProperty
 5. Set kCFStreamPropertyHTTPShouldAutoredirect to kCFBooleanTrue using CFReadStreamSetProperty
 6. open read stream using CFReadStreamOpen
 7. In a loop wait for stream to get opened

while (1)
 {
     if (kCFStreamStatusOpen == CFReadStreamGetStatus)
     {
           if (CFReadStreamHasBytesAvailable)
           {
                 Get Http response header using CFReadStreamCopyProperty
                 Get response code using CFHTTPMessageGetResponseStatusCode
                 if (200 || 206 is response code)
                 SUCCESS
                 else check if response code is 407.
           }
      }
 }

Я пытался использовать следующий код

if (407 == nsiStatusCode)
{
CFStreamError err;
cfAuthentication = CFHTTPAuthenticationCreateFromResponse(NULL, cfHttpResponse);
if ((cfAuthentication) && (CFHTTPAuthenticationIsValid(cfAuthentication, &err)))
{
if (CFHTTPAuthenticationRequiresUserNameAndPassword(cfAuthentication))
{
CFHTTPMessageApplyCredentials(cfHttpRequest, cfAuthentication, (CFStringRef)pnsUserName, (CFStringRef)pnsPassword, &err);
}
}
}

но не может заставить его работать. Как мне обработать код состояния 407 для связи с аутентификационным сервером HTTP?

Заранее спасибо. Vaibhav.

1 Ответ

2 голосов
/ 15 октября 2011

Создание CFHTTPMessageRef

-(CFHTTPMessageRef)buildMessage
{
   NSURL *myURL = [NSURL URLWithString:@"http://myurl.com"];
   NSData *dataToPost = [[NSString stringWithString:@"POST Data It Doesn't Matter What It Is"] dataUsingEncoding:NSUTF8StringEncoding];


   //Create with the default allocator (NULL), a post request,
   //the URL, and pick either
   //kCFHTTPVersion1_0 or kCFHTTPVersion1_1
   CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CSTR("POST"), (CFURLRef)myURL, kCFHTTPVersion1_1);


   CFHTTPMessageSetBody(request, (CFDataRef)dataToPost);


   //Unfortunately, this isn't smart enough to set reasonable headers for you
   CFHTTPMessageSetHeaderFieldValue(request, CFSTR("HOST"), (CFStringRef)[myURL host]);
   CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Content-Length"), (CFStringRef)[NSString stringWithFormat:"%d", [dataToPost length]);
   CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Content-Type"), CFSTR("charset=utf-8"));


   return [NSMakeCollectable(request) autorelease];
}

Отправка его на сервер и считывание ответа

-(CFHTTPMessageRef)performHTTPRequest:(CFHTTPMessageRef)request
{
   CFReadStreamRef requestStream = CFReadStreamCreateForHTTPRequest(NULL, request);
   CFReadStreamOpen(requestStream);


   NSMutableData *responseBytes = [NSMutableData data];


   CFIndex numBytesRead = 0 ;
   do
   {
      UInt8 buf[1024];
      numBytesRead = CFReadStreamRead(requestStream, buf, sizeof(buf));


      if(numBytesRead > 0)
         [responseBytes appendBytes:buf length:numBytesRead];


   } while(numBytesRead > 0);


   CFHTTPMessageRef response = (CFHTTPMessageRef)CFReadStreamCopyProperty(requestStream, kCFStreamPropertyHTTPResponseHeader);
   CFHTTPMessageSetBody(response, (CFDataRef)responseBytes);


   CFReadStreamClose(requestStream);
CFRelease(requestStream);


   return [NSMakeCollectable(response) autorelease];
}  

Добавление аутентификации в запрос HTTP

-(void)addAuthenticationToRequest:(CFHTTPMessageRef)request withResponse:(CFHTTPMessageRef)response
{
   CFHTTPAuthenticationRef authentication = CFHTTPAuthenticationCreateFromResponse(NULL, response);
   [NSMakeCollectable(authentication) autorelease];


   CFStreamError err;
   Boolean success = CFHTTPMessageApplyCredentials(request, authentication, CFSTR("username"), CFSTR("password"), &err);
}  

УстановкаВсе вместе

-(void)magicHappens
{
   CFHTTPMessageRef request = [self buildMessage];
   CFHTTPMessageRef response = [self performHTTPRequest: request];


   UInt32 statusCode;
   statusCode = CFHTTPMessageGetResponseStatusCode(response);


   //An HTTP status code of 401 or 407 indicates that authentication is  
   //required I use an auth count to make sure we don't get stuck in an    
   //infinite loop if our credentials are bad. Sometimes, making the    
   //request more than once lets it go through.
   //I admit I don't know why.


   int authCount = 0;
   while((statusCode == 401 || statusCode == 407) && authCount < 3)
   {
      request = [self buildMessage];
      [self addAuthenticationToRequest:request withResponse:response];


      response = [self performHTTPRequest: request];
      statusCode = CFHTTPMessageGetResponseStatusCode;
      authCount++;
   }


    NSData *responseBodyData = [(NSData*)CFHTTPMessageCopyBody(response) autorelease];
   NSString *responseBody = [[[NSString alloc] initWithData:responseBodyData encoding:NSUTF8StringEncoding] autorelease];


   NSLog(responseBody);
}  

Ссылка на эту ссылку.

...