Ошибка кодирования URL-адреса iOS NSURL

URL-адрес, который открывается в Firefox, браузерах Chrome на рабочем столе, не открывается в WebView на iPhone. Этот URL-адрес предположительно обращается к запросу GET. При создании NSURL без процентного экранирования URL-адрес не создается. При использовании процентного выхода URL-адрес перенаправляется на неверный URL-адрес.

Используется ли другая кодировка в настольных браузерах, а не в iPhone? или мобильный сафари? Существуют ли другие способы кодирования URL-адреса в iOS, кроме использования

-stringByAddingPercentEscapesUsingEncoding
-CFURLCreateStringByAddingPercentEscapes

который генерирует неверные страницы содержимого запроса с сервера.

Любая помощь будет действительно здорово, спасибо.

РЕДАКТИРОВАТЬ:
Сгенерированный URL-адрес выглядит следующим образом:

http://something.test.com/iostest/index.html?{"a":"b"}

Удалось выяснить, что некодирование фигурных скобок вызывает проблему в iOS. как в

NSString *tempUrlSting = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)tempURLA,CFSTR("{}"), CFSTR("\""), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)));
NSURL *tempUrl=[NSURL URLWithString:tempUrlSting];
  1. Если не кодировать фигурные скобки в URL-адресе, а кодировать остальные, используя [ответ Роба] [1], как указано выше. При создании NSURL URL-адрес пуст.
  2. При кодировании фигурных скобок URL-адрес генерируется нормально, но сервер выдает исключение.

Этот Вопрос предлагает использовать CFNetworking.

РЕДАКТИРОВАТЬ
Используется CFNetworking, как показано ниже.

-(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 03.07.2014    source источник
comment
Очень необычно видеть ?, за которым следует JSON. Вы можете увидеть http://my.site.com?json=xxx, где xxx – процент экранированного JSON. Или можно написать серверные скрипты, которые просто исключают тело JSON или запрос. Но обычно вы не просто добавляете JSON в URL-адрес после ?. Это не соответствует правилам URI.   -  person Rob    schedule 07.07.2014
comment
Верно, но это устаревший код, и, к сожалению, я застрял с ним без возможности что-либо изменить на стороне сервера. Я устал использовать CFNetworking, но наткнулся на исключение. Я опубликую код как редактирование. Было бы очень здорово, если бы можно было оказать какую-либо помощь. Спасибо   -  person roshi    schedule 08.07.2014


Ответы (2)


Иногда уже закодированный формат URL, за исключением символа é, который, вероятно, должен быть закодирован как %c3%a9. Настольный браузер довольно либерален с недопустимыми URL-адресами, поэтому он работает в Safari и т. д. Поэтому, если у вас есть NSString и вы хотите преобразовать его в правильную кодировку URL-адреса, используйте приведенный ниже метод класса NSString.

NSURL* url = [NSURL URLWithString:[strURL stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];

person Sreejith Bhatt    schedule 03.07.2014

Вы должны отредактировать свой вопрос, показав нам пример вашего URL и ваших параметров GET. Если вы в процентах экранируете, например, какой-то зарезервированный символ в имени домена или URL-адресе, это предлагает одно решение (например, stringByAddingPercentEscapesUsingEncoding в порядке). Если вы в процентах экранируете более широкий набор зарезервированных символов в параметрах запроса GET (особенно = или +), то stringByAddingPercentEscapesUsingEncoding просто не подходит для работы, и вам придется использовать CFURLCreateStringByAddingPercentEscapes (но только для ключей параметров и их значения, а не в полной строке URL). Я использую метод, подобный следующему, для параметров, когда я добавляю их к URL-адресу:

- (NSString *)percentEscapeURLParameter:(NSString *)string
{ 
    return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                     (CFStringRef)string,
                                                                     NULL,
                                                                     (CFStringRef)@":/?@!$&'()*+,;=",
                                                                     kCFStringEncodingUTF8));
}

Если вы говорите, что CFURLCreateStringByAddingPercentEscapes у вас не работает, вы должны показать нам, как вы его используете. Убедитесь, что вы делаете это только для значений параметра GET, что вы предоставляете необходимый параметр «допустимые символы для экранирования», что вы не экранируете то, чего не должно быть, и т. д.

person Rob    schedule 03.07.2014