41- WKWebView項(xiàng)目實(shí)踐分享(六)- 項(xiàng)目實(shí)踐:User Agent、跨域弛说、白屏挽懦、重定向及其它

系列文章:

設(shè)置User Agent

User Agent百度百科釋義是。中文名為用戶代理木人,簡(jiǎn)稱 UA信柿,它是一個(gè)特殊字符串頭,使得服務(wù)器能夠識(shí)別客戶使用的操作系統(tǒng)及版本醒第、CPU 類型渔嚷、瀏覽器及版本、瀏覽器渲染引擎稠曼、瀏覽器語(yǔ)言形病、瀏覽器插件等。
簡(jiǎn)單理解就是一句話:讓服務(wù)器知道C端設(shè)備的信息,白話點(diǎn)就是漠吻, 你得讓H5后臺(tái)知道打開(kāi)這個(gè)網(wǎng)頁(yè)是從你們公司app上打開(kāi)的量瓜,這對(duì)大數(shù)據(jù)和廣告統(tǒng)計(jì)非常關(guān)鍵。

User Agent

設(shè)置方式兩種途乃,一種是iOS8.0開(kāi)始都使用NSUserDefaults绍傲。另一種是從iOS9.0開(kāi)始,使用WKWebView提供的API:customUserAgent耍共。

 if ([UIDevice currentDevice].systemVersion.floatValue >= 9.0) 
{
NSString *newUserAgent = @"YCWebKit";
      self.wkWebView.customUserAgent = newUserAgent;
}

 if ([UIDevice currentDevice].systemVersion.floatValue < 9.0)
{
NSString *newUserAgent = @"YCWebKit";
      [[NSUserDefaults standardUserDefaults] registerDefaults:@{@"UserAgent":newUserAgent}];
      [[NSUserDefaults standardUserDefaults] synchronize];   
}

注意:
1. NSUserDefaults這種方式一定要在初始化WKWebView之前設(shè)置才有效
**2. 后期項(xiàng)目使用中的過(guò)程中烫饼,遇到了一個(gè)關(guān)于User Agent的坑, 特別注意试读, 設(shè)置的時(shí)候不要覆蓋手機(jī)原生User Agent杠纵, 我們要把我們自己公司的自定義User Agent字段追加到原生后邊可以。否則會(huì)發(fā)生一些意想不到的錯(cuò)誤钩骇。
具體看《42- WKWebView(6) - 補(bǔ)充: 實(shí)踐中的坑》
**

跨域問(wèn)題

跨域分成兩種:

  1. 一個(gè)是在相同請(qǐng)求協(xié)議下比藻,host不同。比如說(shuō)伊履,在http://www.a.com/點(diǎn)擊一個(gè)按鈕跳轉(zhuǎn)到了http://www.b.com/頁(yè)面是這個(gè)就叫做跨域韩容。
  2. 直接請(qǐng)求協(xié)議就不同款违,這也是跨域唐瀑。比如說(shuō):http://www.a.com/https://www.a.com/

跨域?qū)kWebView有什么影響呢?基于上一篇Cookie的方案插爹,經(jīng)過(guò)實(shí)踐發(fā)現(xiàn)哄辣,在iOS11.0以下,WKWebView中HTTPS 對(duì) HTTPS赠尾、HTTP 對(duì) HTTP 的跨域是能載入的力穗。但是沒(méi)辦法跨域用document.cookie設(shè)置cookie,也就是前一頁(yè)面document.cookie中的cookie帶不過(guò)去气嫁。 在iOS11.0以上当窗,使用WKHttpCookieStore,從b.com頁(yè)面執(zhí)行g(shù)oBack()方法返回到上一頁(yè)a.com時(shí)寸宵,a.com的request Header中額外添加設(shè)置的appver和devised兩個(gè)屬性丟失崖面,但是Cookie還在。

跨域問(wèn)題的出現(xiàn)是因?yàn)閃ebKit框架對(duì)跨域進(jìn)行了安全性檢查限制梯影,不允許跨域巫员。那么怎么解決呢?我一共試驗(yàn)了兩種解決方案甲棍。

第一種方案:修復(fù)

在請(qǐng)求過(guò)程中request是readOnly的简识,也就是我們沒(méi)辦法在請(qǐng)求過(guò)程中把丟失的屬性在HTTPHeader中加上,繼續(xù)請(qǐng)求。 所以只能是攔截到具體URL七扰,然后重新賦值Cookie和其它參數(shù)奢赂,執(zhí)行l(wèi)oadRequest。 但是這樣在我們現(xiàn)兩個(gè)問(wèn)題行的導(dǎo)航條需求下戳寸,會(huì)出現(xiàn)兩個(gè)問(wèn)題:

  • webView.backForwardList.backList始終不會(huì)為空呈驶,導(dǎo)致如果點(diǎn)擊返回退出控制器,需要
    手動(dòng)加邏輯處理疫鹊。
  • 當(dāng)在a.com/下不跳轉(zhuǎn)的情況下袖瞻,對(duì)頁(yè)面進(jìn)行操作,界面變更之后拆吆。進(jìn)入b.com/然后使用此
    方法重新loadRequest鏈接a.com/聋迎,頁(yè)面恢復(fù)初始化,之前操作丟失枣耀。

第二種方案:新打開(kāi)一個(gè)webView控制器

這種方案的顧慮如果a.com/要從b.com/頁(yè)面中獲取返回?cái)?shù)據(jù)霉晕,會(huì)導(dǎo)致無(wú)法拿到數(shù)據(jù)。但是從公司H5開(kāi)發(fā)小哥那里分享到經(jīng)驗(yàn)捞奕,一般H5不會(huì)這么做牺堰,取數(shù)據(jù)只是在同一個(gè)頁(yè)面中。那這樣就很簡(jiǎn)單了颅围。

和后臺(tái)約定在http://b.com鏈接后邊加上自定義標(biāo)識(shí)伟葫,比如說(shuō)OPenNewVC=1。那么此時(shí)我們?cè)?code>a.com/中點(diǎn)擊某個(gè)按鈕觸發(fā)的跳轉(zhuǎn)鏈接就是http://b.com?OPenNewVC=1院促,然后在decidePolicyForNavigationAction方法中攔截筏养,然后打開(kāi)新控制器。

設(shè)置重定向

在WKWebView中常拓,網(wǎng)頁(yè)如果有重定向的行為渐溶,會(huì)直接回調(diào)didReceiveServerRedirectForProvisionalNavigation。但是在實(shí)際測(cè)試中發(fā)現(xiàn)弄抬,有的網(wǎng)頁(yè)雖然進(jìn)入了這個(gè)方法茎辐,但是不需要我們手動(dòng)干預(yù),就可以重新跳轉(zhuǎn)到重定向后的頁(yè)面掂恕,你手動(dòng)干預(yù)了反而導(dǎo)致請(qǐng)求不成功拖陆。但是有的網(wǎng)頁(yè),就需要自己重新loadRequest一下才可以竹海。

- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
    if (webView.isLoading
        && ![webView.URL.absoluteString containsString:@".a.com"]
        ) {
        [self loadRequestURL:webView.URL.absoluteString];
    }
}

白屏問(wèn)題

在《騰訊Bugly: WKWebView 那些坑》的關(guān)于白屏問(wèn)題的描述是這樣的:

"WKWebView 自詡擁有更快的加載速度慕蔚,更低的內(nèi)存占用,但實(shí)際上 WKWebView 是一個(gè)多進(jìn)程組件斋配,
Network Loading 以及 UI Rendering 在其它進(jìn)程中執(zhí)行孔飒。初次適配 WKWebView 的時(shí)候灌闺,我們也驚
訝于打開(kāi) WKWebView 后,App 進(jìn)程內(nèi)存消耗反而大幅下降坏瞄,但是仔細(xì)觀察會(huì)發(fā)現(xiàn)桂对,Other Process
的內(nèi)存占用會(huì)增加。在一些用 webGL 渲染的復(fù)雜頁(yè)面鸠匀,使用 WKWebView 總體的內(nèi)存占用(App Pr
ocess Memory + Other Process Memory)不見(jiàn)得比 UIWebView 少很多蕉斜。

在 UIWebView 上當(dāng)內(nèi)存占用太大的時(shí)候,App Process 會(huì) crash缀棍;而在 WKWebView 上當(dāng)總體的內(nèi)
存占用比較大的時(shí)候宅此,WebContent Process 會(huì) crash,從而出現(xiàn)白屏現(xiàn)象爬范。"

總之父腕,就是因?yàn)槟撤N原因,Web Content Process奔潰了青瀑,從而出現(xiàn)白屏現(xiàn)象璧亮。

因?yàn)槲业捻?xiàng)目里,暫時(shí)沒(méi)有遇到這個(gè)問(wèn)題斥难。所以大家可以先看一下騰訊的解決方案枝嘶。

此處等待驗(yàn)證: 需要注意的一點(diǎn)是,我在之前的測(cè)試中哑诊,發(fā)現(xiàn)貌似上邊提到的重定向失敗也會(huì)進(jìn)入這個(gè)方法群扶。但是

處理a標(biāo)簽和_blank

需要通過(guò)navigationAction.targetFrame判斷目標(biāo)frame是不是主frame,如果不是主frame搭儒,那么就說(shuō)明是新開(kāi)一個(gè)tab操作穷当。

- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
    WKFrameInfo *frameInfo = navigationAction.targetFrame;
    if(frameInfo == nil || frameInfo.isMainFrame == NO){
        [webView loadRequest:[YCWebViewCookieTool fixRequest:navigationAction.request]];
    }
    return nil;
}

處理Alert彈框

WKWebView把WebView調(diào)用native彈框的處理也交給我們提茁,我們可以根據(jù)自己的需要進(jìn)行定制淹禾。注意alertView點(diǎn)擊之后需要調(diào)用一下代理方法中的block。

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"溫馨提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }];
    [alert addAction:action1];
    [self presentViewController:alert animated:YES completion:NULL];
    
}


- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"溫馨提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"刪除" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }];
    
    UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }];
    [alert addAction:action1];
    [alert addAction:action2];
    [self presentViewController:alert animated:YES completion:NULL];
}


- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:defaultText message:@"JS調(diào)用輸入框" preferredStyle:UIAlertControllerStyleAlert];
    [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.textColor = [UIColor redColor];
    }];
    
    [alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler([[alert.textFields lastObject] text]);
    }]];
    
    [self presentViewController:alert animated:YES completion:NULL];
}

Https請(qǐng)求的證書(shū)驗(yàn)證

WKWebView中提供了didReceiveAuthenticationChallenge:方法來(lái)判斷茴扁。我們可以彈個(gè)alert讓用戶選擇是否信任铃岔,也可以默認(rèn)直接設(shè)置信任。 以下的處理方式朋友分享的一個(gè)峭火,源頭可能來(lái)自《wkwebview下的https請(qǐng)求》:

/**
 https 請(qǐng)求會(huì)進(jìn)這個(gè)方法毁习,在里面進(jìn)行https證書(shū)校驗(yàn)、白名單域名判斷等操作
 */
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{
    
    /*
     NSURLSessionAuthChallengeUseCredential = 0,                     使用證書(shū)
     NSURLSessionAuthChallengePerformDefaultHandling = 1,            忽略證書(shū)(默認(rèn)的處理方式)
     NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,     忽略書(shū)證, 并取消這次請(qǐng)求
     NSURLSessionAuthChallengeRejectProtectionSpace = 3,            拒絕當(dāng)前這一次, 下一次再詢問(wèn)
     */
    
    NSString *authenticationMethod = [[challenge protectionSpace] authenticationMethod];
    
    // 判斷服務(wù)器返回的證書(shū)類型, 是否是服務(wù)器信任
    if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        
        SecTrustRef secTrustRef = challenge.protectionSpace.serverTrust;
        
        if (secTrustRef != NULL) {// 信任是否為空
            
            SecTrustResultType result;
            
            OSErr er = SecTrustEvaluate(secTrustRef, &result);
            
            if (er != noErr) {// 是否有錯(cuò)誤信息
                
                completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace,nil);
                return;
                
            }else{// 沒(méi)有錯(cuò)誤信息
                
                if (result == kSecTrustResultRecoverableTrustFailure) {// 證書(shū)不受信任
                    CFArrayRef secTrustProperties = SecTrustCopyProperties(secTrustRef);

                    NSArray *arr = CFBridgingRelease(secTrustProperties);

                    NSMutableString *errorStr = [NSMutableString string];

                    for (int i=0;i<arr.count;i++){

                        NSDictionary *dic = [arr objectAtIndex:i];

                        if (i != 0 ) {
                            [errorStr appendString:@" "];

                        }

                        [errorStr appendString:(NSString*)dic[@"value"]];

                    }

                    SecCertificateRef certRef = SecTrustGetCertificateAtIndex(secTrustRef, 0);

                    CFStringRef cfCertSummaryRef = SecCertificateCopySubjectSummary(certRef);

                    NSString *certSummary = (NSString *)CFBridgingRelease(cfCertSummaryRef);

                    NSString *title = @"該服務(wù)器無(wú)法驗(yàn)證";

                    NSString *message = [NSString stringWithFormat:@" 是否通過(guò)來(lái)自%@標(biāo)識(shí)為 %@證書(shū)為%@的驗(yàn)證. \n%@" , @"我的app",webView.URL.host,certSummary, errorStr];

                    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];

                    [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel"

                                                                        style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {


                                                                            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);


                                                                        }]];

                    [alertController addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {

                        NSURLCredential* credential = [NSURLCredential credentialForTrust:secTrustRef];

                        completionHandler(NSURLSessionAuthChallengeUseCredential, credential);

                    }]];

                    // 彈出權(quán)限提示框
                    [self presentViewController:alertController animated:YES completion:^{}];
                    return;
                    
                }else{// 證書(shū)受信任
                    
                    NSURLCredential* credential = [NSURLCredential credentialForTrust:secTrustRef];
                    completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
                    return;
                }
            }
            
        }else{//信任不為空
            completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
        }
    }else{//非服務(wù)器信任
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
    }
}

關(guān)于在線播放視頻

需要注意mediaTypesRequiringUserActionForPlayback這個(gè)屬性設(shè)置哪些媒體資源需要用戶手動(dòng)操作一下才能播放卖丸,也就是否自動(dòng)播放纺且。WKAudiovisualMediaTypeNone代表視頻和音頻資料都自動(dòng)播放。

WKWebViewConfiguration * webConfiguration = [[WKWebViewConfiguration alloc]init];
WKUserContentController *contentController = [[WKUserContentController alloc] init];

// 是否允許HTML5頁(yè)面在線播放視頻稍浆,否則使用native播放器
webConfiguration.allowsInlineMediaPlayback = YES; 

// 是指不需要用戶操作载碌,進(jìn)入webView頁(yè)面視頻自動(dòng)播放
if (YCSystemVersionValue > 10.0) {
    webConfiguration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
}
else if (9.0 < YCSystemVersionValue && YCSystemVersionValue < 10.0) {
    webConfiguration.requiresUserActionForMediaPlayback = NO;
}
else if (8.0 < YCSystemVersionValue && YCSystemVersionValue< 9.0) {
    webConfiguration.mediaPlaybackRequiresUserAction = NO;
}

關(guān)于selectionGranularity屬性

selectionGranularity這個(gè)屬性是設(shè)置了用戶拷貝網(wǎng)頁(yè)內(nèi)容的時(shí)候的粒度猜嘱。粒度可能很不好理解。我們直接找個(gè)新聞網(wǎng)頁(yè)看下設(shè)置之后的效果嫁艇。當(dāng)設(shè)置為WKSelectionGranularityCharacter, 在iOS9上復(fù)制文本沒(méi)有定位光標(biāo)朗伶。
具體可以看下:


iOS

API,from:《WKWebView詳解》

屏幕旋轉(zhuǎn)

// 屏幕旋轉(zhuǎn)
wkWebView.translatesAutoresizingMaskIntoConstraints = NO;
wkWebView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);

NSURLProtocol

WKWebView中使用NSURLProtocol需要使用私有API论皆,而且用了之后有兩個(gè)問(wèn)題。網(wǎng)上的一些方案可以過(guò)審猾漫,但是考慮到我們項(xiàng)目并非必要這個(gè)需求和使用之后的不確定性以及工作量点晴。最終放棄NSURLProtocol。不過(guò)先期也了解了一下悯周,提供大家?guī)灼诲e(cuò)的文章參考:

參考

強(qiáng)烈建議你把下邊的參考文章也快速看下觉鼻,作為拓展和補(bǔ)充:

交流


希望能和大家交流技術(shù)
Blog:http://www.lilongcnc.cc


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末队橙,一起剝皮案震驚了整個(gè)濱河市坠陈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捐康,老刑警劉巖仇矾,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異解总,居然都是意外死亡贮匕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門花枫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)刻盐,“玉大人,你說(shuō)我怎么就攤上這事劳翰《匦浚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵佳簸,是天一觀的道長(zhǎng)乙墙。 經(jīng)常有香客問(wèn)我,道長(zhǎng)生均,這世上最難降的妖魔是什么听想? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮马胧,結(jié)果婚禮上汉买,老公的妹妹穿的比我還像新娘。我一直安慰自己佩脊,他們只是感情好蛙粘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布朽色。 她就那樣靜靜地躺著,像睡著了一般组题。 火紅的嫁衣襯著肌膚如雪葫男。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天崔列,我揣著相機(jī)與錄音梢褐,去河邊找鬼。 笑死赵讯,一個(gè)胖子當(dāng)著我的面吹牛盈咳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播边翼,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼鱼响,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了组底?” 一聲冷哼從身側(cè)響起丈积,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎债鸡,沒(méi)想到半個(gè)月后江滨,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厌均,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年唬滑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棺弊。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡晶密,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出模她,到底是詐尸還是另有隱情稻艰,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布缝驳,位于F島的核電站连锯,受9級(jí)特大地震影響归苍,放射性物質(zhì)發(fā)生泄漏用狱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一拼弃、第九天 我趴在偏房一處隱蔽的房頂上張望夏伊。 院中可真熱鬧,春花似錦吻氧、人聲如沸溺忧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鲁森。三九已至祟滴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間歌溉,已是汗流浹背垄懂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留痛垛,地道東北人草慧。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像匙头,于是被迫代替她去往敵國(guó)和親漫谷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容