美文网首页
使用系统方法编码在URL路径包含#时导致的网页404问题

使用系统方法编码在URL路径包含#时导致的网页404问题

作者: Sweet丶 | 来源:发表于2018-09-12 18:56 被阅读306次

一、问题点

iOS7以上系统中, 对路径编码的方法是

URLString = [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

这个方法在一般一说都是没有问题的,但是如果是在路径的pathCompnets中包含了特殊字符如"#"的情况下, 这个“#”会被编码成“%23”,导致网页404:资源未找到
查找问题原因:

/*
     产生问题的原因:
     * H5端开发人员对“?”后面的参数进行取值时,取到的值会解码,不会有问题;
     * 但是如果路径上有特殊字符,那在访问网页的时候URL的pathCompenents部分,因为H5没有自己做编码处理,会导致找不到路径404错误:
     
     解决思路:
     1. 只对路径里面的参数部分进行编码,其他部分不编码
     2. 截取?往后的字符进行编码
     */
    NSString *URLString1 = @"https://qr.ysepay.com/h5agency/#/shenzhen";
    NSURL *URL_notEncode1 = [NSURL URLWithString:URLString1];
    NSString *URLString_encode1 = [URLString1 stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSURL *URL_Encode1 = [NSURL URLWithString:URLString_encode1];
    NSLog(@"URL_notEncode1 = %@\nURLString_encode1=%@", URL_notEncode1.absoluteString, URL_Encode1.absoluteString);
    // 结论:没有中文时可以使用系统的方法生成URL
    
    NSString *URLString2 = @"https://qr.ysepay.com/h5agency/#/shenzhen?category=电子商务&shopOwner=赵云#wer";
    NSURL *URL_notEncode2 = [NSURL URLWithString:URLString2];
    NSString *URLString_encode2 = [URLString2 stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSURL *URL_Encode2 = [NSURL URLWithString:URLString_encode2];
    NSLog(@"URL_notEncode2 = %@\nURLString_encode2=%@", URL_notEncode2.absoluteString, URL_Encode2.absoluteString);
    // 结论:有中文时需要先编码再使用系统的方法生成URL,但是如果pathCompenents中含有“#”等特殊的字符时,也会被编码导致网页404
    
    NSString *URLString3 = URLString2;
    NSString *lastPathComponent = URLString2.lastPathComponent;// 如果是lastPathComponent,则“?”后面必然是参数
    NSRange queryRange = [lastPathComponent rangeOfString:@"?"];//
    if (queryRange.location != NSNotFound && queryRange.length > 0) {
        NSString *queryOrignal = [lastPathComponent substringWithRange:NSMakeRange(queryRange.location+1, lastPathComponent.length -queryRange.location-1)];
        NSString *queryEncode = [queryOrignal stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        NSString *lastPathComponentEncode = [lastPathComponent stringByReplacingOccurrencesOfString:queryOrignal withString:queryEncode];
        URLString3 = [URLString2.stringByDeletingLastPathComponent stringByAppendingPathComponent:lastPathComponentEncode];
    }
    NSURL *correctURL = [NSURL URLWithString:URLString3];
    // 结论:对参数部分进行编码后再生成URL即可
    NSLog(@"correctURL=%@", correctURL);

二、解决方法

可以利用runtime的特性,交换系统的URLWithString:方法,具体代码如下

+ (void)load
{
    Method orignalMethod = class_getClassMethod(self, @selector(URLWithString:));
    Method exchangeMethod = class_getClassMethod(self, @selector(ys_URLWithString:));
    method_exchangeImplementations(orignalMethod, exchangeMethod);
}

+ (instancetype)ys_URLWithString:(NSString *)URLString
{
    if (URLString.length > 0) {// 中文转码
        
        // 检查有没有进行过编码,有编码的情况下不再进行编码
        // 取参数部分进行编码
        
        NSString *URLString2 = [URLString stringByRemovingPercentEncoding];
        NSString *lastPathComponent = URLString2.lastPathComponent;// 如果是lastPathComponent,则“?”后面必然是参数
        NSRange queryRange = [lastPathComponent rangeOfString:@"?"];//
        if (queryRange.location != NSNotFound && queryRange.length > 0) {
            NSString *queryOrignal = [lastPathComponent substringWithRange:NSMakeRange(queryRange.location+1, lastPathComponent.length -queryRange.location-1)];
            NSString *queryEncode = [queryOrignal stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
            NSString *lastPathComponentEncode = [lastPathComponent stringByReplacingOccurrencesOfString:queryOrignal withString:queryEncode];
            NSString *URLString3 = [URLString2.stringByDeletingLastPathComponent stringByAppendingPathComponent:lastPathComponentEncode];
            
            URLString = URLString3;
        }
        
        return [self ys_URLWithString:URLString];
    }
    return nil;
}

延伸知识

根据网络标准RFC 1738,路径中有特殊字符的情况下,需要使用编码才可以用作URL

网络标准RFC 1738
“只有字母和数字[0-9a-zA-Z]、一些特殊符号“$-_.+!*'(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。”

建议看一下这个博客
https://blog.csdn.net/chenlycly/article/details/51820727

相关文章

  • 使用系统方法编码在URL路径包含#时导致的网页404问题

    一、问题点 iOS7以上系统中, 对路径编码的方法是 这个方法在一般一说都是没有问题的,但是如果是在路径的path...

  • Requests传中文参数问题

    问题描述 使用http协议,进行win系统主机的交互,在包含中文参数时,编码不对,导致参数不符合 解决示例

  • ios 原生网络请求封装(新)

    引用 按需组合 get方法(例子:简易使用) post方法(例子:包含请求头、url编码) upload方法(例子...

  • url 编码

    1. 什么是 url url 访问网页时需要输入的网页地址,表示资源的地点。这个就类似于我们在电脑中使用的文件路径...

  • Moya 使用记录

    今天在使用Moya时,path中含有 ? 经过编码会被转义为 %3F ,导致404请求失败,谷歌半天,找到解决办法...

  • URL 编码 iOS

    URL 编码 iOS 废弃的方法1: 废弃的方法2: 正确方法 ps: 在有些时候,如果业务需要url包含签名之类...

  • iOS 使用 NSBundle 找不到资源文件路径问题

    将视频拖到项目中, 使用以下方法获取资源路径时, URL 为nilNSURL *url = [[NSBundle ...

  • iOS中URL的中文编码和URL拼接字符串的问题

    一、URL中的中文编码问题 在开发中,后端提供的接口中,有个图片的url中带有了中文,导致在创建NSURL时返回为...

  • 4.HTML基础

    1、网页乱码的问题是如何产生的?解决方法? ①保存的编码格式和浏览器解析时的解码格式不匹配导致的。将保存的编码格式...

  • OS X chrome新版谷歌浏览器编码问题

    问题描述:Chrome浏览器在55版本以后无法设置网页编码导致字体无法正常显示。 原因:使用频率低,为了促进网页编...

网友评论

      本文标题:使用系统方法编码在URL路径包含#时导致的网页404问题

      本文链接:https://www.haomeiwen.com/subject/sdgvgftx.html