日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Spring Cloud Gateway 記錄請求應答數據日志操作

瀏覽:96日期:2023-07-30 13:58:45

我就廢話不多說了,大家還是直接看代碼吧~

public class GatewayContext { public static final String CACHE_GATEWAY_CONTEXT = 'cacheGatewayContext'; /** * cache json body */ private String cacheBody; /** * cache formdata */ private MultiValueMap<String, String> formData; /** * cache reqeust path */ private String path; public String getCacheBody() { return cacheBody; } public void setCacheBody(String cacheBody) { this.cacheBody = cacheBody; } public MultiValueMap<String, String> getFormData() { return formData; } public void setFormData(MultiValueMap<String, String> formData) { this.formData = formData; } public String getPath() { return path; } public void setPath(String path) { this.path = path; }}

import java.io.UnsupportedEncodingException;import java.net.URLEncoder;import java.nio.charset.Charset;import java.nio.charset.StandardCharsets;import java.util.List;import java.util.Map;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.core.io.ByteArrayResource;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.core.io.buffer.DataBufferUtils;import org.springframework.core.io.buffer.NettyDataBufferFactory;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpMethod;import org.springframework.http.MediaType;import org.springframework.http.codec.HttpMessageReader;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.http.server.reactive.ServerHttpRequestDecorator;import org.springframework.stereotype.Component;import org.springframework.util.MultiValueMap;import org.springframework.web.reactive.function.server.HandlerStrategies;import org.springframework.web.reactive.function.server.ServerRequest;import org.springframework.web.server.ServerWebExchange;import io.netty.buffer.ByteBufAllocator;import reactor.core.publisher.Flux;import reactor.core.publisher.Mono;// https://segmentfault.com/a/1190000017898354@Componentpublic class LogRequestGlobalFilter implements GlobalFilter { /** * default HttpMessageReader */ private static final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders(); private Logger log = LoggerFactory.getLogger(LogRequestGlobalFilter.class); @Override public Mono<Void> filter( ServerWebExchange exchange, GatewayFilterChain chain) { /** * save request path and serviceId into gateway context */ ServerHttpRequest request = exchange.getRequest(); String path = request.getPath().pathWithinApplication().value(); GatewayContext gatewayContext = new GatewayContext(); gatewayContext.setPath(path); /** * save gateway context into exchange */ exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT, gatewayContext); HttpHeaders headers = request.getHeaders(); MediaType contentType = headers.getContentType(); log.info('start-------------------------------------------------'); log.info('HttpMethod:{},Url:{}', request.getMethod(), request.getURI().getRawPath()); log.info('Headers token: {}', headers.getFirst('token')); if (request.getMethod() == HttpMethod.GET) { log.info('end-------------------------------------------------'); } if (request.getMethod() == HttpMethod.POST) { Mono<Void> voidMono = null; if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)) { voidMono = readBody(exchange, chain, gatewayContext); } if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) { voidMono = readFormData(exchange, chain, gatewayContext); } return voidMono; } /* log.debug( '[GatewayContext]ContentType:{},Gateway context is set with {}', contentType, gatewayContext);*/ return chain.filter(exchange); } /** * ReadFormData * * @param exchange * @param chain * @return */ private Mono<Void> readFormData( ServerWebExchange exchange, GatewayFilterChain chain, GatewayContext gatewayContext) { final ServerHttpRequest request = exchange.getRequest(); HttpHeaders headers = request.getHeaders(); return exchange.getFormData() .doOnNext(multiValueMap -> { gatewayContext.setFormData(multiValueMap); log.info('Post x-www-form-urlencoded:{}', multiValueMap); log.info( 'end-------------------------------------------------'); }) .then(Mono.defer(() -> { Charset charset = headers.getContentType().getCharset(); charset = charset == null ? StandardCharsets.UTF_8 : charset; String charsetName = charset.name(); MultiValueMap<String, String> formData = gatewayContext.getFormData(); /** * formData is empty just return */ if (null == formData || formData.isEmpty()) { return chain.filter(exchange); } StringBuilder formDataBodyBuilder = new StringBuilder(); String entryKey; List<String> entryValue; try { /** * repackage form data */ for (Map.Entry<String, List<String>> entry : formData.entrySet()) { entryKey = entry.getKey(); entryValue = entry.getValue(); if (entryValue.size() > 1) {for (String value : entryValue) { formDataBodyBuilder.append(entryKey).append('=') .append( URLEncoder.encode(value, charsetName)) .append('&');} } else {formDataBodyBuilder .append(entryKey).append('=').append(URLEncoder .encode(entryValue.get(0), charsetName)) .append('&'); } } } catch (UnsupportedEncodingException e) { // ignore URLEncode Exception } /** * substring with the last char ’&’ */ String formDataBodyString = ''; if (formDataBodyBuilder.length() > 0) { formDataBodyString = formDataBodyBuilder.substring(0,formDataBodyBuilder.length() - 1); } /** * get data bytes */ byte[] bodyBytes = formDataBodyString.getBytes(charset); int contentLength = bodyBytes.length; ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator( request) {/** * change content-length * * @return */@Overridepublic HttpHeaders getHeaders() { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.putAll(super.getHeaders()); if (contentLength > 0) { httpHeaders.setContentLength(contentLength); } else { httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, 'chunked'); } return httpHeaders;}/** * read bytes to Flux<Databuffer> * * @return */@Overridepublic Flux<DataBuffer> getBody() { return DataBufferUtils .read(new ByteArrayResource(bodyBytes), new NettyDataBufferFactory( ByteBufAllocator.DEFAULT), contentLength);} }; ServerWebExchange mutateExchange = exchange.mutate().request(decorator).build(); /* log.info('[GatewayContext]Rewrite Form Data :{}', formDataBodyString);*/ return chain.filter(mutateExchange); })); } /** * ReadJsonBody * * @param exchange * @param chain * @return */ private Mono<Void> readBody( ServerWebExchange exchange, GatewayFilterChain chain, GatewayContext gatewayContext) { /** * join the body */ return DataBufferUtils.join(exchange.getRequest().getBody()) .flatMap(dataBuffer -> { /* * read the body Flux<DataBuffer>, and release the buffer * //TODO when SpringCloudGateway Version Release To G.SR2,this can be update with the new version’s feature * see PR https://github.com/spring-cloud/spring-cloud-gateway/pull/1095 */ byte[] bytes = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(bytes); DataBufferUtils.release(dataBuffer); Flux<DataBuffer> cachedFlux = Flux.defer(() -> { DataBuffer buffer =exchange.getResponse().bufferFactory().wrap(bytes); DataBufferUtils.retain(buffer); return Mono.just(buffer); }); /** * repackage ServerHttpRequest */ ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {@Overridepublic Flux<DataBuffer> getBody() { return cachedFlux;} }; /** * mutate exchage with new ServerHttpRequest */ ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build(); /** * read body string with default messageReaders */ return ServerRequest.create(mutatedExchange, messageReaders) .bodyToMono(String.class) .doOnNext(objectValue -> {log.info('PostBody:{}', objectValue);log.info( 'end-------------------------------------------------');gatewayContext.setCacheBody(objectValue); /* log.debug('[GatewayContext]Read JsonBody:{}',objectValue);*/ }).then(chain.filter(mutatedExchange)); }); }}

import lombok.extern.slf4j.Slf4j;import org.reactivestreams.Publisher;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.core.Ordered;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.core.io.buffer.DataBufferFactory;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpMethod;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.http.server.reactive.ServerHttpResponseDecorator;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Flux;import reactor.core.publisher.Mono;import java.net.InetSocketAddress;import java.net.URI;import java.nio.CharBuffer;import java.nio.charset.Charset;import java.nio.charset.StandardCharsets;import java.util.concurrent.atomic.AtomicReference;@Component@Slf4jpublic class LogResponseGlobalFilter implements GlobalFilter, Ordered { private static final String REQUEST_PREFIX = 'Request Info [ '; private static final String REQUEST_TAIL = ' ]'; private static final String RESPONSE_PREFIX = 'Response Info [ '; private static final String RESPONSE_TAIL = ' ]'; private StringBuilder normalMsg = new StringBuilder(); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); DataBufferFactory bufferFactory = response.bufferFactory(); normalMsg.append(RESPONSE_PREFIX); ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) { @Override public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { if (body instanceof Flux) { Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body; return super.writeWith(fluxBody.map(dataBuffer -> { // probably should reuse buffers byte[] content = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(content); String responseResult = new String(content, Charset.forName('UTF-8')); normalMsg.append('status=').append(this.getStatusCode()); normalMsg.append(';header=').append(this.getHeaders()); normalMsg.append(';responseResult=').append(responseResult); normalMsg.append(RESPONSE_TAIL); log.info(normalMsg.toString()); return bufferFactory.wrap(content); })); } return super.writeWith(body); // if body is not a flux. never got there. } }; return chain.filter(exchange.mutate().response(decoratedResponse).build()); } @Override public int getOrder() { return -2; }}

補充知識:Spring Cloud Gateway 2.x 打印 Log

場景

在服務網關層面,需要打印出用戶每次的請求body和其他的參數,gateway使用的是Reactor響應式編程,和Zuul網關獲取流的寫法還有些不同,

不過基本的思路是一樣的,都是在filter中讀取body流,然后緩存回去,因為body流,框架默認只允許讀取一次。

思路

1. 添加一個filter做一次請求的攔截

GatewayConfig.java

添加一個配置類,配置一個高優先級的filter,并且注入一個PayloadServerWebExchangeDecorator 對request和response做包裝的類。

package com.demo.gateway2x.config;import com.demo.gateway2x.decorator.PayloadServerWebExchangeDecorator;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.Ordered;import org.springframework.core.annotation.Order;import org.springframework.web.server.WebFilter;@Configurationpublic class GatewayConfig { @Bean @Order(Ordered.HIGHEST_PRECEDENCE) //過濾器順序 public WebFilter webFilter() { return (exchange, chain) -> chain.filter(new PayloadServerWebExchangeDecorator(exchange)); }}

PayloadServerWebExchangeDecorator.java

這個類中,我們實現了框架的ServerWebExchangeDecorator類,同時注入了自定義的兩個類,PartnerServerHttpRequestDecorator 和 PartnerServerHttpResponseDecorator ,

這兩個類用于后面對請求與響應的攔截。

package com.demo.gateway2x.decorator;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.web.server.ServerWebExchange;import org.springframework.web.server.ServerWebExchangeDecorator;public class PayloadServerWebExchangeDecorator extends ServerWebExchangeDecorator { private PartnerServerHttpRequestDecorator requestDecorator; private PartnerServerHttpResponseDecorator responseDecorator; public PayloadServerWebExchangeDecorator(ServerWebExchange delegate) { super(delegate); requestDecorator = new PartnerServerHttpRequestDecorator(delegate.getRequest()); responseDecorator = new PartnerServerHttpResponseDecorator(delegate.getResponse()); } @Override public ServerHttpRequest getRequest() { return requestDecorator; } @Override public ServerHttpResponse getResponse() { return responseDecorator; }}

2. 在請求進入時,對request做一次攔截

PartnerServerHttpRequestDecorator.java

這個類實現了 ServerHttpRequestDecorator , 并在構造函數中,使用響應式編程,調用了打印log的方法,注意關注 Mono<DataBuffer> mono = DataBufferUtils.join(flux); ,

這里將Flux合并成了一個Mono,因為如果不這么做,body內容過多,將會被分段打印,這里是一個恒重要的點,

在打印RequestParamsHandle.chain打印過日志后,我們又返回了一個dataBuffer,用作向下傳遞,否則dataBuffer被讀取過一次后就不能繼續使用了。

package com.demo.gateway2x.decorator;import lombok.extern.slf4j.Slf4j;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.core.io.buffer.DataBufferUtils;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.http.server.reactive.ServerHttpRequestDecorator;import reactor.core.publisher.Flux;import reactor.core.publisher.Mono;import static reactor.core.scheduler.Schedulers.single;@Slf4jpublic class PartnerServerHttpRequestDecorator extends ServerHttpRequestDecorator { private Flux<DataBuffer> body; public PartnerServerHttpRequestDecorator(ServerHttpRequest delegate) { super(delegate); Flux<DataBuffer> flux = super.getBody(); if (ParamsUtils.CHAIN_MEDIA_TYPE.contains(delegate.getHeaders().getContentType())) { Mono<DataBuffer> mono = DataBufferUtils.join(flux); body = mono.publishOn(single()).map(dataBuffer -> RequestParamsHandle.chain(delegate, log, dataBuffer)).flux(); } else { body = flux; } } @Override public Flux<DataBuffer> getBody() { return body; }}

RequestParamsHandle.java

這個類主要用來讀取dataBuffer并做了日志打印處理,也可以做一些其他的例如參數校驗等使用。

package com.demo.gateway2x.decorator;import com.alibaba.fastjson.JSON;import org.slf4j.Logger;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.util.StringUtils;import java.util.HashMap;import java.util.Map;public class RequestParamsHandle { public static <T extends DataBuffer> T chain(ServerHttpRequest delegate, Logger log, T buffer) { ParamsUtils.BodyDecorator bodyDecorator = ParamsUtils.buildBodyDecorator(buffer); // 參數校驗 和 參數打印 log.info('Payload: {}', JSON.toJSONString(validParams(getParams(delegate, bodyDecorator.getBody())))); return (T) bodyDecorator.getDataBuffer(); } public static Map<String,Object> getParams(ServerHttpRequest delegate, String body) { // 整理參數 Map<String,Object> params = new HashMap<>(); if (delegate.getQueryParams() != null) { params.putAll(delegate.getQueryParams()); } if (!StringUtils.isEmpty(body)) { params.putAll(JSON.parseObject(body)); } return params; } public static Map<String,Object> validParams(Map<String,Object> params) { // todo 參數校驗 return params; }}

3. 在結果返回時,對response做一次攔截

PartnerServerHttpResponseDecorator.java

這個類和上面的request的異曲同工,攔截響應流,并做記錄入處理。

package com.demo.gateway2x.decorator;import lombok.extern.slf4j.Slf4j;import org.reactivestreams.Publisher;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.core.io.buffer.DataBufferUtils;import org.springframework.http.MediaType;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.http.server.reactive.ServerHttpResponseDecorator;import reactor.core.publisher.Flux;import reactor.core.publisher.Mono;import static reactor.core.scheduler.Schedulers.single;@Slf4jpublic class PartnerServerHttpResponseDecorator extends ServerHttpResponseDecorator { PartnerServerHttpResponseDecorator(ServerHttpResponse delegate) { super(delegate); } @Override public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) { return super.writeAndFlushWith(body); } @Override public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { final MediaType contentType = super.getHeaders().getContentType(); if (ParamsUtils.CHAIN_MEDIA_TYPE.contains(contentType)) { if (body instanceof Mono) { final Mono<DataBuffer> monoBody = (Mono<DataBuffer>) body; return super.writeWith(monoBody.publishOn(single()).map(dataBuffer -> ResponseParamsHandle.chain(log, dataBuffer))); } else if (body instanceof Flux) { Mono<DataBuffer> mono = DataBufferUtils.join(body); final Flux<DataBuffer> monoBody = mono.publishOn(single()).map(dataBuffer -> ResponseParamsHandle.chain(log, dataBuffer)).flux(); return super.writeWith(monoBody); } } return super.writeWith(body); }}

ResponseParamsHandle.java

響應流的日志打印

package com.demo.gateway2x.decorator;import org.slf4j.Logger;import org.springframework.core.io.buffer.DataBuffer;public class ResponseParamsHandle { public static <T extends DataBuffer> T chain(Logger log, T buffer) { ParamsUtils.BodyDecorator bodyDecorator = ParamsUtils.buildBodyDecorator(buffer); // 參數校驗 和 參數打印 log.info('Payload: {}', bodyDecorator.getBody()); return (T) bodyDecorator.getDataBuffer(); }}

下面是實際操作,發送一次http請求:

Spring Cloud Gateway 記錄請求應答數據日志操作

Spring Cloud Gateway 記錄請求應答數據日志操作

控制臺log結果:

Spring Cloud Gateway 記錄請求應答數據日志操作

github源碼地址:https://github.com/qiaomengnan16/gateway-2x-log-demo

總結

gateway和zuul打印參數的方式思路是一致的,只是gateway采用的是reactor,寫法上與zuul的直接讀取流有些不同,這里需要知道的是Flux需要轉換為Mono這個地方,如果不轉換容易分多批打印。

以上這篇Spring Cloud Gateway 記錄請求應答數據日志操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美国产日本| 久热精品在线| 男人的天堂久久精品| 日韩在线观看| 国产成人精品亚洲日本在线观看| 国产成人免费av一区二区午夜| 久久三级毛片| 国产一区2区| 一区二区三区四区日本视频| 91精品一区国产高清在线gif| 久久久天天操| 免费成人在线影院| 麻豆国产精品| 欧美/亚洲一区| 蜜臀久久久99精品久久久久久| 日本不卡一区二区三区| 国产福利资源一区| 99久久久久国产精品| 亚洲欧美日韩视频二区| 日本午夜精品久久久久| 国产传媒av在线| 美女尤物久久精品| 美日韩一区二区三区| 人人香蕉久久| 亚洲3区在线| 欧美日韩免费看片| 亚洲精品麻豆| 久久网站免费观看| 欧美日韩一视频区二区| 国产91久久精品一区二区| 欧美一级网站| 米奇777超碰欧美日韩亚洲| 国产日韩欧美一区二区三区 | 1024精品久久久久久久久| 人人精品久久| 在线成人直播| 国精品产品一区| 日韩三级精品| 欧美日韩激情| 色综合五月天| 综合干狼人综合首页| 91日韩欧美| 日韩高清成人在线| 在线综合亚洲| 韩国精品主播一区二区在线观看| 91成人在线网站| 色综合视频一区二区三区日韩 | 男人的天堂久久精品| 神马日本精品| 国产精品国产三级国产在线观看| 亚洲激情黄色| 婷婷色综合网| 亚洲播播91| 国产成人精品福利| 国产精品啊啊啊| 久久国内精品视频| 日本少妇一区二区| 亚洲精品日韩久久| 亚洲午夜免费| 在线精品视频一区| 亚洲一区日韩在线| 久久亚洲精品伦理| 免费在线看一区| 男女性色大片免费观看一区二区 | 成人三级高清视频在线看| 国产精品久久久久久久久久白浆| 久久国产婷婷国产香蕉| 国产美女精品视频免费播放软件| 欧美亚洲一级| 久久这里只有| 日本а中文在线天堂| 色偷偷色偷偷色偷偷在线视频| 精品久久视频| 成人在线丰满少妇av| 久久婷婷激情| 亚洲免费播放| 色8久久久久| 国产精品传媒麻豆hd| 激情久久99| 亚洲性图久久| 亚洲毛片在线| 国产乱码精品一区二区亚洲| 国产精品高清一区二区| 国产成人精品一区二区三区视频| 久久精品国内一区二区三区水蜜桃| 亚洲一区欧美激情| 欧美在线黄色| 成人在线超碰| 99国产精品久久久久久久成人热| 日本v片在线高清不卡在线观看| 国产精品3区| 136国产福利精品导航网址| 日韩福利视频一区| 国产麻豆久久| 日韩高清三区| 欧美福利在线| 美女久久精品| 婷婷五月色综合香五月| av在线最新| 青草国产精品久久久久久| 私拍精品福利视频在线一区| 91福利精品在线观看| 美女av在线免费看| 日本视频一区二区| 国产视频一区三区| 久久精品国内一区二区三区| 国产精品2区| 97精品国产一区二区三区| 久久国产精品久久w女人spa| 久久精品国产亚洲aⅴ | 99日韩精品| 天堂中文在线播放| 久久av电影| 欧美一级网站| 深夜日韩欧美| 亚洲91视频| 久久三级毛片| 国产精品极品国产中出| 亚洲精品婷婷| 蜜桃视频第一区免费观看| 欧美1区免费| 日韩大片免费观看| 大香伊人久久精品一区二区| 国产精品第一| 国产欧美日韩一区二区三区在线| 亚洲人成精品久久久| 日韩专区在线视频| 日韩中文字幕不卡| 亚洲青青久久| 日本欧美韩国一区三区| 亚洲欧洲免费| 亚洲一区av| 91成人在线网站| 国产精品片aa在线观看 | 国产亚洲高清一区| 日本午夜精品久久久久| 欧美色综合网| 久久精品色播| www.51av欧美视频| 久久毛片亚洲| 99久久婷婷| 三级在线观看一区二区| 日本麻豆一区二区三区视频| 亚洲久久视频| 国产精品国码视频| 亚洲精品成人图区| 婷婷精品进入| 欧美一级网站| 中文字幕人成乱码在线观看| 免费av一区| 日本国产一区| 国产精品久久观看| 男人天堂欧美日韩| 国产欧美日韩精品一区二区三区 | 91精品国产福利在线观看麻豆| 999在线观看精品免费不卡网站| 美女久久一区| 久久久国产精品入口麻豆| 国产在线|日韩| 亚洲精品日本| 久久精品在线| 国产劲爆久久| 免费不卡在线观看| av中文字幕在线观看第一页| 亚洲欧美日韩一区在线观看| 精品国产不卡| 亚洲视频国产| 久久久久久久久久久妇女 | 亚洲国产专区校园欧美| 国产日本精品| 中文在线不卡| 亚洲女同av| 里番精品3d一二三区| 亚洲香蕉视频| 日韩一区二区久久| 欧美三区四区| 免费看一区二区三区| 日日摸夜夜添夜夜添国产精品| 色爱综合av| 欧美激情aⅴ一区二区三区 | 欧美一级二级三级视频| 久久久久99| 精品欠久久久中文字幕加勒比| 亚洲精品影院在线观看| 亚洲一区二区免费看| 亚洲h色精品| 免费在线亚洲欧美| 老司机精品视频网| 国产精品久久久久9999高清| 欧美日韩 国产精品| 91精品丝袜国产高跟在线| 免费观看在线色综合| 中日韩男男gay无套| 亚洲欧美伊人| 女人天堂亚洲aⅴ在线观看| 欧美亚洲国产激情| 国产白浆在线免费观看| 色婷婷综合网| 欧美aa在线观看| 欧美1级日本1级|