NSURL с фигурными скобками

NSURL не поддерживает использование фигурных скобок (например, {}) в URL-адресах. Мое приложение должно взаимодействовать с сервером, который требует использования фигурных скобок в URL-адресе. Я рассматриваю возможность использования мостов для написания сетевого кода на Python или C++ или даже переписываю код C для NSURL, чтобы он принимал фигурные скобки. Процентные побеги не принимаются моим удаленным сервером.

Есть ли у меня другие хорошие альтернативы?

РЕДАКТИРОВАТЬ: Объяснено, почему добавлениеPercentEscapesUsingEncoding и тому подобное не работает для меня здесь.


person Owen Pierce    schedule 01.12.2011    source источник
comment
Возможно, вы захотите обновить заголовок своего вопроса на NSURL с фигурными скобками - я думаю, вы предполагаете, что вам нужна альтернатива...   -  person bryanmac    schedule 01.12.2011


Ответы (3)


Будет ли это работать для вас, если вы избежите фигурных скобок?

Этот код:

// escape {} with %7B and %7D
NSURL *url = [NSURL URLWithString:@"http://somesite.com/%7B7B643FB915-845C-4A76-A071-677D62157FE07D%7D.htm"];
NSLog(@"%@", url);

// {} don't work and return null
NSURL *badurl = [NSURL URLWithString:@"http://somesite.com/{7B643FB915-845C-4A76-A071-677D62157FE07D}.htm"];
NSLog(@"%@", badurl);

Результаты:

2011-11-30 21:25:06.655 Craplet[48922:707] http://somesite.com/%7B7B643FB915-845C-4A76-A071-677D62157FE07D%7D.htm
2011-11-30 21:25:06.665 Craplet[48922:707] (null)

Итак, побег, кажется, работает

Вот как вы можете программно избежать URL-адреса:

NSString *escapedUrlString = [unescaped stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding];

РЕДАКТИРОВАТЬ:

В своем комментарии ниже вы сказали, что ваш сервер не будет принимать закодированные фигурные скобки, и были ли другие альтернативы. Во-первых, я бы попытался починить сервер. Если это невозможно ... Я не пробовал это с фигурными скобками и т. Д. ... но уровень ниже сетевых классов NS - это CFNetworking.

Посмотри это:

http://developer.apple.com/library/ios/#documentation/Networking/Conceptual/CFNetwork/CFHTTPTasks/CFHTTPTasks.html#//apple_ref/doc/uid/TP30001132-CH5-SW2

Из этого документа:

 CFStringRef url = CFSTR("http://www.apple.com");
 CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);
 CFStringRef requestMethod = CFSTR("GET");

 ....

Еще раз, не пробовал, и я бегу. можете попробовать позже, но если слой не работает, ваши первые варианты - переместиться вниз по стеку.

person bryanmac    schedule 01.12.2011
comment
Привет, Брайан, спасибо за ответ! К сожалению, похоже, что сервер не принимает процент экранированных значений для фигурных скобок. Есть ли способ сформировать запрос GET с явными фигурными скобками в цели c? - person Owen Pierce; 01.12.2011
comment
Я добавил примечание о CFNetworking — один из вариантов — продолжать двигаться вниз по стеку. Но, если возможно, я бы попытался починить сервер :) - person bryanmac; 04.12.2011
comment
Спасибо за обновление. Мы обнаружили, что нас сбила с толку небольшая ошибка кодирования в другом месте. Проблема решена, но я сохраню этот код для дальнейшего использования на случай, если возникнут другие проблемы с сетью. - person Owen Pierce; 06.12.2011
comment
У меня такая же проблема. Необходимо создать запрос GET без кодирования фигурных скобок. Не могли бы вы предоставить код, который генерирует запрос с использованием CFNetwork? Я пробовал, что в ссылке выдается исключение доступа EXEC BAD. - person roshi; 04.07.2014
comment
Я пытаюсь использовать @ для экранирования строки, но не могу этого сделать. Он игнорирует @ в начале строки. - person Nathan McKaskle; 27.06.2015

Ответ Брайана просто великолепен (+1 ему!), но другим решением было бы использование NSString stringByAddingPercentEscapesUsingEncoding:.

Как это:

NSString * originalURLAsString = [NSString stringWithString: @"http://somesite.com/{7B643FB915-845C-4A76-A071-677D62157FE07D}.htm"];
NSString * properlyEncodedString = [originalURLAsString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
NSURL * url = [NSURL URLWithString: properlyEncodedString];

Я надеюсь, что эта информация поможет вам!

person Michael Dautermann    schedule 01.12.2011
comment
+1 - редактировал мой, как вы добавили к этому ответу - наши сохранения пересеклись :) - person bryanmac; 01.12.2011
comment
Привет Михаил, спасибо за публикацию! Этот трюк не сработал для меня, потому что другая сторона ожидает явных фигурных скобок, а не процентов экранированных значений. Знаете ли вы способ сформировать запрос GET с явными фигурными скобками в цели c? - person Owen Pierce; 01.12.2011
comment
у вас есть контроль над сервером, с которым вы разговариваете? Серверы всегда должны обрабатывать URL-адреса с экранированием в процентах. - person Michael Dautermann; 01.12.2011
comment
У меня нет контроля над сервером, с которым я разговариваю. Фигурные скобки находятся в строке запроса. - person Owen Pierce; 02.12.2011

Для вызова с помощью CFNetwork можно использовать следующие

-(void)getDataFromUrl{
    CFStringRef tempURLA = CFSTR("http://my.test.server/iostest/index.html?{\"a\":\"b\"}");
    CFStringRef tempUrlSting = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)tempURLA,CFSTR("{}"), CFSTR("\""), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));

    CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, tempUrlSting, NULL);

    CFStringRef requestMethod = CFSTR("GET");
    CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL,kCFHTTPVersion1_1);

    CFStringRef headerFieldName = CFSTR("Accept");
    CFStringRef headerFieldValue = CFSTR("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
    CFHTTPMessageSetHeaderFieldValue(myRequest, headerFieldName, headerFieldValue);


    [self performHTTPRequest:myRequest];

}

-(void)performHTTPRequest:(CFHTTPMessageRef)request {
    CFURLRef gotdatab = (__bridge CFURLRef)(CFBridgingRelease(CFHTTPMessageCopyRequestURL(request)));
//    NSLog(@"(CFHTTPMessageRef request  %@",gotdatab);

    CFReadStreamRef requestStream = CFReadStreamCreateForHTTPRequest(NULL, request);

    CFReadStreamOpen(requestStream);

    NSMutableData *responseBytes = [NSMutableData data];
    NSError *error;

    while (TRUE) {

        if (CFReadStreamHasBytesAvailable(requestStream)) {
            UInt8 streambuffer[1024];
            int readBytes = CFReadStreamRead (requestStream,streambuffer,sizeof(streambuffer));
            NSLog(@"Read: %d",readBytes);
            [responseBytes appendBytes:streambuffer length:readBytes];
        }

        if (CFReadStreamGetStatus(requestStream) == kCFStreamStatusError) {

            error = (NSError*)CFBridgingRelease(CFReadStreamCopyError (requestStream));
            if ([error code] == 61) {
                // connection refused
                NSLog(@"Error occured: %d",[error code]);
            }
            break;
        }
        if (CFReadStreamGetStatus(requestStream) == kCFStreamStatusAtEnd) {
            NSLog(@"Stream reached end!");
            error = nil;
            break;
        }

    }//
    CFHTTPMessageRef response = (CFHTTPMessageRef)CFReadStreamCopyProperty(requestStream, kCFStreamPropertyHTTPResponseHeader);

    if (response==NULL) {
        NSLog(@"response is null");
        return;
    }
}

Вышеупомянутое было сделано с использованием примеров из здесь и здесь

Но даже вышеупомянутый метод имеет ту же проблему. То есть: если {} не закодированы, URL-адрес не генерируется. Если {} закодированы, сервер не возвращает правильное значение.

Любые другие предложения по решению этой проблемы с сообщениями?

person roshi    schedule 08.07.2014