中文字幕日韩一区二区_国产一区二区av_国产毛片av_久久久久国产一区_色婷婷电影_国产一区二区精品

一個(gè)完整的ASP.NET 2.0 URL重寫方案[翻譯]

這篇文章描述了一個(gè)完整的 ASP.NET 2.0 URL 重寫方案。這個(gè)方案使用正則表達(dá)式來(lái)定義重寫規(guī)則并解決通過(guò)虛擬 URLs 訪問(wèn)頁(yè)面產(chǎn)生回發(fā)事件的一些可能的困難。

為什么要重寫 URL ?

將 URL 重寫方法應(yīng)用到你的 ASP.NET 應(yīng)用程序的兩個(gè)主要原因是:可用性和可維護(hù)性。

可用性

誰(shuí)都知道,相對(duì)于難于辨認(rèn)的帶參數(shù)的長(zhǎng)的查詢路徑,用戶更喜歡一些短的、簡(jiǎn)潔的 URL。任何時(shí)候,一個(gè)容易記住和敲入的路徑比添加到收藏夾更有用。其次,當(dāng)一個(gè)瀏覽器的收藏夾不可用時(shí),記住的地址總比在搜索引擎中輸入關(guān)鍵字進(jìn)行搜索,然后再查找要強(qiáng)的多。比較下面的兩個(gè)地址:

 

(1)

http://www.somebloghost.com/Blogs/Posts.ASPx?Year=2006&Month=12&Day=10

(2)

http://www. somebloghost.com/Blogs/2006/12/10/

 

第一個(gè) URL 包含了查詢字符串;第二個(gè)URL包含的信息可以讓用戶清楚的看到他看的東西,它還可以使用戶更容易的修改地址欄的內(nèi)容,如:http://www.somehost.com/Blogs/2006/12/.

可維護(hù)性

在很多WEB應(yīng)用程序中,開(kāi)發(fā)人員經(jīng)常會(huì)將頁(yè)面從一個(gè)目錄移到另一個(gè)目錄,讓我們假設(shè)一開(kāi)始有兩個(gè)可用頁(yè)面: http://www.somebloghost.com/Info/Copyright.ASPx 和 http://www.somebloghost.com/Support/Contacts.ASPx,但是后來(lái)開(kāi)發(fā)者將 Copyright.ASPx 和 Contacts.ASPx 移到了 Help 目錄,用戶收藏起來(lái)地址就需要重新定位。這個(gè)問(wèn)題雖然可以簡(jiǎn)單的用 Response.Redirect(new location) 來(lái)解決,但是如果有成百上千的頁(yè)面呢?應(yīng)用程序中就會(huì)包含大量的無(wú)效鏈接。

使用 URL 重寫,允許用戶只需修改配置文件,這種方法可以讓開(kāi)發(fā)者將web應(yīng)用程序邏輯結(jié)構(gòu)與物理結(jié)構(gòu)獨(dú)立開(kāi)來(lái)。

ASP.NET 2.0 中的原有的URL 映射

ASP.NET 2.0 為 web 應(yīng)用程序提供了一個(gè)開(kāi)箱即用的映射靜態(tài) URL 的解決方案。這個(gè)方案不用編寫代碼就可以在 web.config 中將舊的 URLs 映射到新的地址。 要使用 URL 映射,只需在 web.config 文件的 system.web 節(jié)中創(chuàng)建一個(gè)新的 urlMappings 節(jié) ,并添加要映射的地址 (“ ~/ ”指向應(yīng)用程序的根目錄):

<urlMappings enabled="true">

   <add url="~/Info/Copyright.ASPx" mappedUrl="~/Help/Copyright.ASPx" />

   <add url="~/Support/Contacts.ASPx" mappedUrl="~/Help/Contacts.ASPx" />

</urlMappings>

這樣,如果用戶輸入 http://www.somebloghost.com/Support/Contacts.ASPx, 它將看到 http://www.somebloghost.com/Help/Contacts.ASPx , 而他并不知道那個(gè)頁(yè)已經(jīng)移除。

這個(gè)方案對(duì)于只有兩個(gè)頁(yè)面被移到其它位置的情況是足夠的。但它對(duì)有一打的需要重定位的頁(yè)或者需要?jiǎng)?chuàng)建一個(gè)整潔的URL來(lái)說(shuō),它是不合適的。另一個(gè)使用ASP.NET 的原有的URL映射技術(shù)的不太好的地方是:如果 Contacts.ASPx 頁(yè)包含的元素在回發(fā)到服務(wù)器時(shí)(這是非常可能的), 用戶將會(huì)驚奇的發(fā)現(xiàn)地址 http://www.somebloghost.com/Support/Contacts.ASPx 卻變成了 http://www.somebloghost.com/Help/Contacts.ASPx

。  這是因?yàn)?a href=/itjie/ASPjishu/ target=_blank class=infotextkey>ASP.NET 引擎用頁(yè)面的實(shí)際地址修改了表單formaction 屬性 ,所以表單就變成了下面的樣子:

<form name="formTest" method="post"
action="http://www.simple-talk.com/Help/Contacts.ASPx" id="formTest">

</form>

這樣看來(lái),URL 映射在ASP.NET 2.0 中幾乎是無(wú)用的。我們應(yīng)當(dāng)能夠使用一個(gè)映射規(guī)則來(lái)指定一系列相似的 URL。最好的解決方案就是使用正則表達(dá)式 ( Wikipedia 上可以查看概覽,and 在 .NET 下的實(shí)現(xiàn)可以查看 MSDN), 但由于 ASP.NET 2.0 映射不支持正則表達(dá)式,所以我們需要開(kāi)發(fā)一個(gè)內(nèi)建到 URL 映射的不同的方案- URL 重寫模塊。 最好的方法就是創(chuàng)建一個(gè)可重用的、簡(jiǎn)單的配置模塊來(lái)實(shí)現(xiàn),顯然我們應(yīng)創(chuàng)建一個(gè) HTTP 模塊 (關(guān)于 HTTP 模塊的詳細(xì)信息請(qǐng)查看 MSDN 雜志) 并在獨(dú)立的程序集中實(shí)現(xiàn)。要使這個(gè)程序集簡(jiǎn)單易用,我們應(yīng)實(shí)現(xiàn)這個(gè)重寫引擎的可配置性,即能夠在 web.config 中指定規(guī)則。

 

 

在開(kāi)發(fā)過(guò)程中,我們應(yīng)能使這個(gè)重寫模塊打開(kāi)或關(guān)閉 (比如你有一個(gè)較難捕獲的bug,而它可能是由不正確的重寫模塊引起的)這樣在 web.config 中對(duì)重寫模塊的配置節(jié)進(jìn)行打開(kāi)或關(guān)閉就成為一個(gè)選擇。這樣,在 web.config 中,一個(gè)配置節(jié)的示例如下:

<rewriteModule>

  <rewriteOn>true</rewriteOn>

  <rewriteRules>

      <rule source="(/d+)/(/d+)/(/d+)/"
         destination="Posts.ASPx?Year=$1&Month=$2&Day=$3"/>

      <rule source="(.*)/Default.ASPx"
         destination="Default.ASPx?Folder=$1"/>

  </rewriteRules>

</rewriteModule>

這樣,所有像: http://localhost/Web/2006/12/10/ 這樣的請(qǐng)示,將會(huì)在內(nèi)部將會(huì)用帶參數(shù)的請(qǐng)求重定向到 Posts.ASPx 。

請(qǐng)注意: web.config 是一個(gè)結(jié)構(gòu)良好的 XML 文件, 它禁止在屬性值中使用 & 符號(hào),所以在例子中,應(yīng)當(dāng)使用 & 代替。

要在配置文件中使用這個(gè)重寫模塊,還需要注冊(cè)節(jié)和指定處理模塊,像下面這樣增加一個(gè)configSections配置節(jié):

 <configSections>

    <sectionGroup name="modulesSection">

      <section name="rewriteModule" type="RewriteModule.
RewriteModuleSectionHandler, RewriteModule"/>

    </sectionGroup>

  </configSections>

這樣你就可以在 configSections 節(jié)的后面這樣使用了:

<modulesSection>

    <rewriteModule>

      <rewriteOn>true</rewriteOn>

      <rewriteRules>

              <rule source="(/d+)/(/d+)/(/d+)/" destination="Post.ASPx?Year=$1&Month=$2&Day=$3"/>

              <rule source="(.*)/Default.ASPx" destination="Default.ASPx?Folder=$1"/>

      </rewriteRules>

    </rewriteModule>

  </modulesSection>

另一個(gè)我們?cè)陂_(kāi)發(fā)重寫模塊過(guò)程中要做的就是還需要允許在虛擬路徑中傳遞參數(shù),象這樣: http://www.somebloghost.com/2006/12/10/?Sort=Desc&SortBy=Date 。所以我們還需要有一個(gè)檢測(cè)通過(guò)虛擬 URL 傳遞參數(shù)的解決方案

 

 

接下來(lái)讓我們來(lái)創(chuàng)建類庫(kù)。首先,我們要引用 System.Web 程序集,這樣我們可以實(shí)現(xiàn)一些基于 web 特殊功能。如果要使我們的模塊能夠訪問(wèn) web.config,還需要引用 System.Configuration 程序集。

 

處理配置節(jié)

要能處理 web.config 中的配置,我們必需創(chuàng)建一個(gè)實(shí)現(xiàn)了 IConfigurationSectionHandler 接口的類 (詳情查看 MSDN )。如下:

using System;

using System.Collections.Generic;

using System.Text;

using System.Configuration;

using System.Web;

using System.Xml;

 

 

namespace RewriteModule

{

    public class RewriteModuleSectionHandler : IConfigurationSectionHandler

    {

 

        private XmlNode _XmlSection;

        private string _RewriteBase;

        private bool _RewriteOn;

 

        public XmlNode XmlSection

        {

            get { return _XmlSection; }

        }

 

        public string RewriteBase

        {

            get { return _RewriteBase; }

        }

 

        public bool RewriteOn

        {

            get { return _RewriteOn; }

        }

        public object Create(object parent,
                            object configContext,
                            System.Xml.XmlNode section)

        {

            // set base path for rewriting module to

            // application root

            _RewriteBase = HttpContext.Current.Request.ApplicationPath + "/";

 

            // process configuration section

            // from web.config

            try

            {

                _XmlSection = section;

                _RewriteOn = Convert.ToBoolean(
                            section.SelectSingleNode("rewriteOn").InnerText);

            }

            catch (Exception ex)

            {

                throw (new Exception("Error while processing RewriteModule
configuration section.", ex));

            }

            return this;

        }

    }

}

RewriteModuleSectionHandler 類將在 web.config 中的 XmlNode 通過(guò)調(diào)用 Create 方法初始化。XmlNode 類的 SelectSingleNode 方法被用來(lái)返回模塊的配置值。

使用重寫的 URL 的參數(shù)

在處理象 http://www. somebloghost.com/Blogs/gaidar/?Sort=Asc (這是一個(gè)帶參數(shù)的虛擬 URL ) 虛擬的 URLS 時(shí),能夠清楚的辨別通過(guò)虛擬路徑傳遞的參數(shù)是非常重要的,如下:

<rule source="(.*)/Default.ASPx" destination="Default.ASPx?Folder=$1"/>,

你可能使用這樣的 URL:

http://www. somebloghost.com/gaidar/?Folder=Blogs

它的效果和下面的相似:

http://www. somebloghost.com/Blogs/gaidar/

要處理這個(gè)問(wèn)題,我們需要對(duì)'虛擬路徑參數(shù)' 進(jìn)行包裝。這可以是通過(guò)一個(gè)靜態(tài)的方法去訪問(wèn)當(dāng)前的參數(shù)集:

using System;

using System.Collections.Generic;

using System.Text;

using System.Collections.Specialized;

using System.Web;

 

namespace RewriteModule

{

 

    public class RewriteContext

    {

        // returns actual RewriteContext instance for

        // current request

        public static RewriteContext Current

        {

            get

            {

                // Look for RewriteContext instance in

                // current HttpContext. If there is no RewriteContextInfo

                // item then this means that rewrite module is turned off

                if(HttpContext.Current.Items.Contains("RewriteContextInfo"))

                    return (RewriteContext)
HttpContext.Current.Items["RewriteContextInfo"];

                else

                    return new RewriteContext();

            }

        }

 

        public RewriteContext()

        {

            _Params = new NameValueCollection();

            _InitialUrl = String.Empty;

        }

 

        public RewriteContext(NameValueCollection param, string url)

        {

            _InitialUrl = url;

            _Params = new NameValueCollection(param);

           

        }

 

        private NameValueCollection _Params;

 

        public NameValueCollection Params

        {

            get { return _Params; }

            set { _Params = value; }

        }

 

        private string _InitialUrl;

 

        public string InitialUrl

        {

            get { return _InitialUrl; }

            set { _InitialUrl = value; }

        }

    }

}

可以看到,這樣就可以通過(guò)RewriteContext.Current 集合來(lái)訪問(wèn) “虛擬路徑參數(shù)”了,所有的參數(shù)都被指定成了虛擬路徑或頁(yè)面,而不是像查詢字符串那樣了。

重寫 URL

接下來(lái),讓我們嘗試重寫。首先,我們要讀取配置文件中的重寫規(guī)則。其次,我們要檢查那些在 URL 中與規(guī)則不符的部分,如果有,進(jìn)行重寫并以適當(dāng)?shù)捻?yè)執(zhí)行。

創(chuàng)建一個(gè) HttpModule:

class RewriteModule : IHttpModule
{

public void Dispose() { }
public void Init(HttpApplication context)

{}

}

當(dāng)我們添加 RewriteModule_BeginRequest 方法以處理不符合規(guī)則的 URL時(shí),我們要檢查給定的 URL 是否包含參數(shù),然后調(diào)用 HttpContext.Current.RewritePath 來(lái)進(jìn)行控制并給出合適的 ASP.NET 頁(yè)。

using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

using System.Configuration;

using System.Xml;

using System.Text.RegularExpressions;

using System.Web.UI;

using System.IO;

using System.Collections.Specialized;

 

namespace RewriteModule

{

    class RewriteModule : IHttpModule

    {

 

        public void Dispose() { }

 

        public void Init(HttpApplication context)

        {

            // it is necessary to

            context.BeginRequest += new EventHandler(
                 RewriteModule_BeginRequest);

        }

 

        void RewriteModule_BeginRequest(object sender, EventArgs e)

        {

 

            RewriteModuleSectionHandler cfg =
(RewriteModuleSectionHandler)
ConfigurationManager.GetSection
("modulesSection/rewriteModule");

 

            // module is turned off in web.config

            if (!cfg.RewriteOn) return;

 

            string path = HttpContext.Current.Request.Path;

 

            // there us nothing to process

            if (path.Length == 0) return;

 

            // load rewriting rules from web.config

            // and loop through rules collection until first match

            XmlNode rules = cfg.XmlSection.SelectSingleNode("rewriteRules");

            foreach (XmlNode xml in rules.SelectNodes("rule"))

            {

                try

                {

                    Regex re = new Regex(
                     cfg.RewriteBase + xml.Attributes["source"].InnerText,
                     RegexOptions.IgnoreCase);

                    Match match = re.Match(path);

                    if (match.Success)

                    {

                        path = re.Replace(
                             path,
                             xml.Attributes["destination"].InnerText);

                        if (path.Length != 0)

                        {

                            // check for QueryString parameters

                       if(HttpContext.Current.Request.QueryString.Count != 0)

                       {

                       // if there are Query String papameters

                       // then append them to current path

                       string sign = (path.IndexOf('?') == -1) ? "?" : "&";

                       path = path + sign +
                          HttpContext.Current.Request.QueryString.ToString();

                       }

                       // new path to rewrite to

                       string rew = cfg.RewriteBase + path;

                       // save original path to HttpContext for further use

                       HttpContext.Current.Items.Add(

                         "OriginalUrl",

                         HttpContext.Current.Request.RawUrl);

                       // rewrite

                       HttpContext.Current.RewritePath(rew);

                       }

                       return;

                    }

                }

                catch (Exception ex)

                {

                    throw (new Exception("Incorrect rule.", ex));

                }

            }

            return;

        }

 

    }

}

 

這個(gè)方法必須注冊(cè):

public void Init(HttpApplication context)

{

 context.BeginRequest += new EventHandler(RewriteModule_BeginRequest);

}

但這些僅僅完成了一半,因?yàn)橹貙懩K還要處理表單的回發(fā)和虛擬路徑參數(shù)集合,而這段代碼中你會(huì)發(fā)現(xiàn)并沒(méi)處理這些。讓我們先把虛擬路徑參數(shù)放到一邊,先來(lái)正確地處理最主要的回發(fā)。

如果我們運(yùn)行上面的代碼,并通過(guò)查看 ASP.NET 的 HTML 源代碼 的 action 會(huì)發(fā)現(xiàn),它竟然包含了一個(gè) ASP.NET 的實(shí)際路徑頁(yè)。例如,我們使用頁(yè) ~/Posts.ASPx 來(lái)處理像 http://www. somebloghost.com/Blogs/2006/12/10/Default.ASPx 的請(qǐng)求, 發(fā)現(xiàn) action="/Posts.ASPx"。這意味著用戶并沒(méi)有使用虛擬路徑進(jìn)行回發(fā),而是使用了實(shí)際的 http://www. somebloghost.com/Blog.ASPx. 這個(gè)并不是我們需要的。所以,需要加一段代碼來(lái)處理這些不希望的結(jié)果。

首先,我們要在 HttpModule 注冊(cè)和實(shí)現(xiàn)一個(gè)另外的方法:

        public void Init(HttpApplication context)

        {

            // it is necessary to

            context.BeginRequest += new EventHandler(
                 RewriteModule_BeginRequest);

            context.PreRequestHandlerExecute += new EventHandler(
                 RewriteModule_PreRequestHandlerExecute);

        }

 

      void RewriteModule_PreRequestHandlerExecute(object sender, EventArgs e)

        {

            HttpApplication app = (HttpApplication)sender;

            if ((app.Context.CurrentHandler is Page) &&
                 app.Context.CurrentHandler != null)

            {

                Page pg = (Page)app.Context.CurrentHandler;

                pg.PreInit += new EventHandler(Page_PreInit);

            }

        }

這個(gè)方法檢查用戶是否請(qǐng)求了一個(gè)正常的 ASP.NET 頁(yè),然后為該頁(yè)的 PreInit 事件增加處理過(guò)程。這兒 RewriteContext 將處理實(shí)際參數(shù),然后二次重寫URL。二次重寫是必需的,以使 ASP.NET 能夠在它的表單的action屬性中使用一個(gè)虛擬路徑。

void Page_PreInit(object sender, EventArgs e)

        {

            // restore internal path to original

            // this is required to handle postbacks

            if (HttpContext.Current.Items.Contains("OriginalUrl"))

            {

              string path = (string)HttpContext.Current.Items["OriginalUrl"];

 

              // save query string parameters to context

              RewriteContext con = new RewriteContext(
                HttpContext.Current.Request.QueryString, path);

 

              HttpContext.Current.Items["RewriteContextInfo"] =  con;

 

              if (path.IndexOf("?") == -1)

                  path += "?";

              HttpContext.Current.RewritePath(path);

            }

        }

最后,我們來(lái)看一下在我們的重寫模塊程序集中的三個(gè)類:

 

在 web.config 中注冊(cè)重寫模塊

要使用重寫模塊,需要在配置文件中的 httpModules 節(jié)注冊(cè)重寫模塊,如下:

<httpModules>

<add name="RewriteModule" type="RewriteModule.RewriteModule, RewriteModule"/>

</httpModules>

使用重寫模塊

在使用重寫模塊時(shí),需要注意:

  • 在 web.config 中來(lái)使用一些特殊字符是不可能的,因?yàn)樗且粋€(gè)結(jié)構(gòu)良好的 XML 文件,因此,你只能用 HTML 編碼的字符代替,如:使用 & 代替 &。
  • 要在你的 ASPX 中使用相對(duì)路徑,需要在HTML標(biāo)簽調(diào)用 ResolveUrl 方法,如: <img src="<%=ResolveUrl("~/Images/Test.jpg")%>" />。
  • Bear in mind the greediness of regular expressions and put rewriting rules to web.config in order of their greediness, for instance:
<rule source="Directory/(.*)/(.*)/(.*)/(.*).ASPx"
destination="Directory/Item.ASPx?
Source=$1&Year=$2&ValidTill=$3&Sales=$4"/>
<rule source="Directory/(.*)/(.*)/(.*).ASPx"
destination="Directory/Items.ASPx?
Source=$1&Year=$2&ValidTill=$3"/>
<rule source="Directory/(.*)/(.*).ASPx"
destination="Directory/SourceYear.ASPx?
Source=$1&Year=$2&"/>
<rule source="Directory/(.*).ASPx"
destination="Directory/Source.ASPx?Source=$1"/>
  • 如果你要在頁(yè)面中使用 RewriteModule 而不使用 .ASPx,就必須在 IIS 中進(jìn)行配置以使用期望的擴(kuò)展映射到請(qǐng)求頁(yè),如下節(jié)所述:

IIS 配置: 使用帶擴(kuò)展的重寫模塊代替 .ASPx

要使用帶擴(kuò)展的重寫模塊代替 .ASPx (如 .html or .xml), 必須配置 IIS ,以使這些擴(kuò)展映射到 ASP.NET 引擎 (ASP.NET ISAPI 擴(kuò)展)。要進(jìn)行這些設(shè)置,需要以管理員身份登錄。

打開(kāi) IIS 管理控制臺(tái),并選擇你要配置的站點(diǎn)的虛擬路徑:

Windows XP (IIS 5)
Virtual Directory "RW"                                

 

Windows 2003 Server (IIS 6)
Default Web Site

然后在虛擬路徑標(biāo)簽上點(diǎn)擊 Configuration… 按鈕  (或如果要使用整個(gè)站點(diǎn)都做映射就選擇主目錄標(biāo)簽)。

Windows XP (IIS 5)                     

Windows 2003 Server (IIS 6)

接下來(lái),點(diǎn)擊添加按鈕,并輸入一個(gè)擴(kuò)展,你還需要指定一個(gè) ASP.NET ISAPI 擴(kuò)展,注意去掉選項(xiàng)的對(duì)勾以檢查文件是否存在。

如果你要把所有的擴(kuò)展都映射到 ASP.NET,對(duì)Windows XP上的 IIS 5 來(lái)說(shuō)只需要設(shè)置 .* 到 ASP.NET ISAPI ,但對(duì) IIS 6 就不一樣了,點(diǎn)擊“添加”然后指定 ASP.NET ISAPI 擴(kuò)展。

總結(jié)

現(xiàn)在,我們已經(jīng)創(chuàng)建了一個(gè)簡(jiǎn)單的但非常強(qiáng)大的 ASP.NET 重寫模塊,它支持可基于正則表達(dá)式的 URLs 和頁(yè)面回發(fā),這個(gè)解決方案是容易實(shí)現(xiàn)的,并且提供給用戶的例子也是可用的,它可以用簡(jiǎn)短的、整潔的URL來(lái)替代查詢字符串參數(shù)。  要使用這個(gè)模塊,只需簡(jiǎn)單在你的應(yīng)用程序中對(duì) RewriteModule 進(jìn)行引用,然后在 web.config 文件中添加幾行代碼以使你不想顯示的 URL 通過(guò)正則表達(dá)式代替。這個(gè)重寫模塊是很容易部署的,因?yàn)橹恍枰趙eb.config中修改任何“虛擬”的URL即可,如果你需要進(jìn)行測(cè)試,還可以對(duì)重寫模塊進(jìn)行關(guān)閉。

要想對(duì)重寫模塊有一個(gè)深入的了解,你可以查看本文提供的原代碼。我相信你會(huì)發(fā)現(xiàn)這是一個(gè)比ASP.NET提供的原始映射更好的體驗(yàn)。

AspNet技術(shù)一個(gè)完整的ASP.NET 2.0 URL重寫方案[翻譯],轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 国产亚洲成av人在线观看导航 | 精品一区二区三区日本 | 国产精品欧美一区二区三区不卡 | 欧美一级黄色网 | 久久久久一区二区 | 美女久久 | 欧美成人精品在线观看 | 在线色| 免费在线毛片 | 欧美一级全黄 | 久久国产欧美日韩精品 | 国产露脸对白88av | 国产成人短视频在线观看 | 亚洲综合一区二区三区 | 91在线第一页 | 欧美无乱码久久久免费午夜一区 | 久久精品一区二区视频 | 欧美aaaaaaaaaa| 青青草一区| www日韩| 国产成人福利在线观看 | 日韩在线精品 | 日本在线免费视频 | 黄色高清视频 | 久久久久久久久久久久久久久久久久久久 | 国产精品99 | 欧美伊人| 久久久久亚洲 | 成人一区二区三区在线 | 伊人看片 | 欧美a级成人淫片免费看 | 三级免费毛片 | 免费a大片 | 91影视| 日韩欧美不卡 | 一区二区三区国产好 | 97人人超碰 | 天天干干| 超碰人人91 | 久久久av| 亚洲97|