public static String getRealIp(ServerHttpRequest request) { final String X_FORWARDED_HEADER = "X-Forwarded-For"; final String X_REAL_HEADER = "X-Real-IP"; final String UNKNOWN = "unknown"; final List<String> forwardedHeaders = request.getHeaders().get(X_FORWARDED_HEADER); String ip = CollectionUtils.isEmpty(forwardedHeaders) ? CommonsConstant.BLANK : forwardedHeaders.get(0); if (StringUtils.isNotEmpty(ip) && !UNKNOWN.equalsIgnoreCase(ip)) { int index = ip.indexOf(CommonsConstant.COMMA); if (index != -1) { return ip.substring(0, index); } else { return ip; } } final List<String> realHeaders = request.getHeaders().get(X_REAL_HEADER); ip = CollectionUtils.isEmpty(realHeaders) ? CommonsConstant.BLANK : realHeaders.get(0); if (StringUtils.isNotEmpty(ip) && !UNKNOWN.equalsIgnoreCase(ip)) { return ip; } return request.getRemoteAddress() == null ? CommonsConstant.BLANK : request.getRemoteAddress().toString(); }
<S extends WebClient.RequestHeadersSpec<S>> Mono<S> configure( WebClient.RequestHeadersUriSpec<S> spec, String applicationId, ServerHttpRequest request) { Mono<Application> applicationMono = this.applicationRepository .findById(applicationId); Mono<AccessToken> accessTokenMono = this.accessTokenService .issueToken(applicationId); // / proxy / {applicationId} / ** // ^___^___^________^________^__^ // 0___1___2________3________4__5 PathContainer wildcard = request.getPath().subPath(5); return Mono.when(applicationMono, accessTokenMono) // .map(tpl -> spec .uri(tpl.getT1().getUrl() + "/cloudfoundryapplication/" + wildcard.value()) .header(AUTHORIZATION, "bearer " + tpl.getT2().getToken()) // .header(REFERER, request.getHeaders().getFirst(REFERER))); }
@Override public Mono<Authentication> convert(ServerWebExchange exchange) { ServerHttpRequest request = exchange.getRequest(); String authorization = request.getHeaders().getFirst("Authorization"); if(authorization == null) { return Mono.empty(); } String credentials = authorization.substring("Basic ".length(), authorization.length()); byte[] decodedCredentials = Base64.getDecoder().decode(credentials); String decodedAuthz = new String(decodedCredentials); String[] userParts = decodedAuthz.split(":"); if(userParts.length != 2) { return Mono.empty(); } String username = userParts[0]; String password = userParts[1]; return Mono.just(new UsernamePasswordAuthenticationToken(username, password)); }
public GatewayFilter apply(String regex, String replacement) { return (exchange, chain) -> { ServerHttpRequest req = exchange.getRequest(); addOriginalRequestUrl(exchange, req.getURI()); String path = req.getURI().getPath(); String newPath = path.replaceAll(regex, replacement); ServerHttpRequest request = req.mutate() .path(newPath) .build(); exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI()); return chain.filter(exchange.mutate().request(request).build()); }; }
public GatewayFilter apply(String prefix) { return (exchange, chain) -> { ServerHttpRequest req = exchange.getRequest(); addOriginalRequestUrl(exchange, req.getURI()); String newPath = prefix + req.getURI().getPath(); ServerHttpRequest request = req.mutate() .path(newPath) .build(); exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI()); if (log.isTraceEnabled()) { log.trace("Prefixed URI with: "+prefix+" -> "+request.getURI()); } return chain.filter(exchange.mutate().request(request).build()); }; }
@Override protected Observable<Void> resumeWithFallback() { if (this.fallbackUri == null) { return super.resumeWithFallback(); } //TODO: copied from RouteToRequestUrlFilter URI uri = exchange.getRequest().getURI(); boolean encoded = containsEncodedQuery(uri); URI requestUrl = UriComponentsBuilder.fromUri(uri) .host(null) .port(null) .uri(this.fallbackUri) .build(encoded) .toUri(); exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl); ServerHttpRequest request = this.exchange.getRequest().mutate().uri(requestUrl).build(); ServerWebExchange mutated = exchange.mutate().request(request).build(); return RxReactiveStreams.toObservable(HystrixGatewayFilterFactory.this.dispatcherHandler.handle(mutated)); }
@RequestMapping(path = REQUEST_MAPPING_PATH, method = {RequestMethod.GET, RequestMethod.HEAD, RequestMethod.POST, RequestMethod.PUT, RequestMethod.PATCH, RequestMethod.DELETE, RequestMethod.OPTIONS}) public Mono<Void> endpointProxy(@PathVariable("instanceId") String instanceId, ServerHttpRequest request, ServerHttpResponse response) { String endpointLocalPath = getEndpointLocalPath(request.getPath().pathWithinApplication().value()); URI uri = UriComponentsBuilder.fromPath(endpointLocalPath) .query(request.getURI().getRawQuery()) .build(true) .toUri(); return super.forward(instanceId, uri, request.getMethod(), request.getHeaders(), () -> BodyInserters.fromDataBuffers(request.getBody())).flatMap(clientResponse -> { response.setStatusCode(clientResponse.statusCode()); response.getHeaders().addAll(filterHeaders(clientResponse.headers().asHttpHeaders())); return response.writeWith(clientResponse.body(BodyExtractors.toDataBuffers())); }); }
@Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); final String LIMIT_KEY = "Limit-Key"; List<String> limitKeyHeaders = request.getHeaders().get(LIMIT_KEY); if (!CollectionUtils.isEmpty(limitKeyHeaders) && StringUtils.isNotBlank(limitKeyHeaders.get(0)) && !limit(new RequestLimit(RemoteAddressUtils.getRealIp(request), request.getURI().getPath(), limitKeyHeaders.get(0), requestBean.getRange(), requestBean.getCount()))) { exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); return Mono.empty(); } return chain.filter(exchange); }
@GetMapping public Mono<ResponseEntity<String>> get(@PathVariable String applicationId, ServerHttpRequest request) { return configure(this.webClient.get(), applicationId, request) // .flatMap(spec -> spec.exchange() // .flatMap(res -> res.bodyToMono(String.class) // .map(b -> ResponseEntity.status(res.statusCode()).body(b)) // .switchIfEmpty(emptyResponse(res)))); }
@PostMapping public Mono<ResponseEntity<String>> post(@PathVariable String applicationId, ServerHttpRequest request) { return configure(this.webClient.post(), applicationId, request) // .flatMap(spec -> spec .header(CONTENT_TYPE, request.getHeaders().getFirst(CONTENT_TYPE)) // .body(request.getBody(), DataBuffer.class) // .exchange() // .flatMap(res -> res.bodyToMono(String.class) // .map(b -> ResponseEntity.status(res.statusCode()).body(b)) // .switchIfEmpty(emptyResponse(res)))); }
@Override public MatchResult matches(ServerWebExchange exchange) { ServerHttpRequest request = exchange.getRequest(); if(this.method != null && !this.method.equals(request.getMethod())) { return MatchResult.NO_MATCH; } String path = helper.getLookupPathForRequest(exchange); boolean match = pathMatcher.match(pattern, path); if(!match) { return MatchResult.NO_MATCH; } Map<String,String> pathVariables = pathMatcher.extractUriTemplateVariables(pattern, path); Map<String,Object> variables = new HashMap<>(pathVariables); return new MatchResult(match, variables); }
@Override public MatchResult matches(ServerWebExchange exchange) { ServerHttpRequest request = exchange.getRequest(); if(this.method != null && !this.method.equals(request.getMethod())) { return MatchResult.notMatch(); } String path = helper.getLookupPathForRequest(exchange); boolean match = pathMatcher.match(pattern, path); if(!match) { return MatchResult.notMatch(); } Map<String,String> pathVariables = pathMatcher.extractUriTemplateVariables(pattern, path); Map<String,Object> variables = new HashMap<>(pathVariables); return MatchResult.match(variables); }
public GatewayFilter apply(String template) { UriTemplate uriTemplate = new UriTemplate(template); return (exchange, chain) -> { PathMatchInfo variables = exchange.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE); ServerHttpRequest req = exchange.getRequest(); addOriginalRequestUrl(exchange, req.getURI()); Map<String, String> uriVariables; if (variables != null) { uriVariables = variables.getUriVariables(); } else { uriVariables = Collections.emptyMap(); } URI uri = uriTemplate.expand(uriVariables); String newPath = uri.getPath(); exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri); ServerHttpRequest request = req.mutate() .path(newPath) .build(); return chain.filter(exchange.mutate().request(request).build()); }; }
public GatewayFilter apply(List<String> headersToRemove) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest().mutate() .headers(httpHeaders -> { for (String header : headersToRemove) { httpHeaders.remove(header); } }) .build(); return chain.filter(exchange.mutate().request(request).build()); }; }
public GatewayFilter apply(String header) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest().mutate() .headers(httpHeaders -> httpHeaders.remove(header)) .build(); return chain.filter(exchange.mutate().request(request).build()); }; }
public GatewayFilter apply(String name, String value) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest().mutate() .headers(httpHeaders -> httpHeaders.set(name, value)) .build(); return chain.filter(exchange.mutate().request(request).build()); }; }
public GatewayFilter apply(String name, String value) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest().mutate() .header(name, value) .build(); return chain.filter(exchange.mutate().request(request).build()); }; }
public GatewayFilter apply(String parameter, String value) { return (exchange, chain) -> { URI uri = exchange.getRequest().getURI(); StringBuilder query = new StringBuilder(); String originalQuery = uri.getQuery(); if (StringUtils.hasText(originalQuery)) { query.append(originalQuery); if (originalQuery.charAt(originalQuery.length() - 1) != '&') { query.append('&'); } } //TODO urlencode? query.append(parameter); query.append('='); query.append(value); try { URI newUri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), query.toString(), uri.getFragment()); ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build(); return chain.filter(exchange.mutate().request(request).build()); } catch (URISyntaxException ex) { throw new IllegalStateException("Invalid URI query: \"" + query.toString() + "\""); } }; }
/** Override to add annotations not defined in {@link TraceKeys}. */ protected void addRequestTags(Span span, ServerHttpRequest request) { keysInjector().addRequestTags(span, request.getURI(), request.getMethod().toString()); for (String name : traceKeys().getHttp().getHeaders()) { List<String> values = request.getHeaders().get(name); if (values != null && !values.isEmpty()) { String key = traceKeys().getHttp().getPrefix() + name.toLowerCase(); String value = values.size() == 1 ? values.get(0) : StringUtils.collectionToDelimitedString(values, ",", "'", "'"); keysInjector().tagSpan(span, key, value); } } }
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR); String scheme = requestUrl.getScheme(); if (isAlreadyRouted(exchange) || (!"http".equals(scheme) && !"https".equals(scheme))) { return chain.filter(exchange); } setAlreadyRouted(exchange); ServerHttpRequest request = exchange.getRequest(); HttpMethod method = request.getMethod(); RequestBodySpec bodySpec = this.webClient.method(method) .uri(requestUrl) .headers(httpHeaders -> { httpHeaders.addAll(request.getHeaders()); //TODO: can this support preserviceHostHeader? httpHeaders.remove(HttpHeaders.HOST); }); RequestHeadersSpec<?> headersSpec; if (requiresBody(method)) { headersSpec = bodySpec.body(BodyInserters.fromDataBuffers(request.getBody())); } else { headersSpec = bodySpec; } return headersSpec.exchange() // .log("webClient route") .flatMap(res -> { ServerHttpResponse response = exchange.getResponse(); response.getHeaders().putAll(res.headers().asHttpHeaders()); response.setStatusCode(res.statusCode()); // Defer committing the response until all route filters have run // Put client response as ServerWebExchange attribute and write response later NettyWriteResponseFilter exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res); return chain.filter(exchange); }); }
private String sampledHeader(ServerHttpRequest request) { return getHeader(request, Span.SAMPLED_NAME); }
/** * Creates a span and appends it as the current request's attribute */ private Span createSpan(ServerHttpRequest request, ServerWebExchange exchange, boolean skip, Span spanFromAttribute, String name) { Span spanFromRequest = null; if (spanFromAttribute != null) { if (log.isDebugEnabled()) { log.debug("Span has already been created - continuing with the previous one"); } return spanFromAttribute; } Span parent = spanExtractor().joinTrace(new ServerHttpRequestTextMap(request)); if (parent != null) { if (log.isDebugEnabled()) { log.debug("Found a parent span " + parent + " in the request"); } addRequestTagsForParentSpan(request, parent); spanFromRequest = parent; tracer().continueSpan(spanFromRequest); if (parent.isRemote()) { parent.logEvent(Span.SERVER_RECV); } exchange.getAttributes().put(TRACE_REQUEST_ATTR, spanFromRequest); if (log.isDebugEnabled()) { log.debug("Parent span is " + parent + ""); } } else { if (skip) { spanFromRequest = tracer().createSpan(name, NeverSampler.INSTANCE); } else { String header = getHeader(request, Span.SPAN_FLAGS); if (Span.SPAN_SAMPLED.equals(header)) { spanFromRequest = tracer().createSpan(name, new AlwaysSampler()); } else { spanFromRequest = tracer().createSpan(name); } addRequestTags(spanFromRequest, request); } spanFromRequest.logEvent(Span.SERVER_RECV); exchange.getAttributes().put(TRACE_REQUEST_ATTR, spanFromRequest); exchange.getAttributes().put(TRACE_SPAN_WITHOUT_PARENT, spanFromRequest); if (log.isDebugEnabled()) { log.debug("No parent span present - creating a new span"); } } return spanFromRequest; }
private String getHeader(ServerHttpRequest request, String headerName) { List<String> list = request.getHeaders().get(headerName); return list == null ? "" : list.isEmpty() ? "" : list.get(0); }
/** * In order not to send unnecessary data we're not adding request tags to the server * side spans. All the tags are there on the client side. */ private void addRequestTagsForParentSpan(ServerHttpRequest request, Span spanFromRequest) { if (spanFromRequest.getName().contains("parent")) { addRequestTags(spanFromRequest, request); } }
ServerHttpRequestTextMap(ServerHttpRequest delegate) { this.delegate = delegate; this.additionalHeaders.put(ZipkinHttpSpanMapper.URI_HEADER, delegate.getPath().pathWithinApplication().value()); }