private static boolean isValidPath(HttpRequest req) { return PathAndQuery.parse(req.path()) != null; }
@Override public CompletionStage<Void> beforeInitiatingSso(ServiceRequestContext ctx, HttpRequest req, MessageContext<AuthnRequest> message, SamlIdentityProviderConfig idpConfig) { final String requestedPath = req.path(); if (requestedPath.length() <= 80) { // Relay the requested path by default. final SAMLBindingContext sub = message.getSubcontext(SAMLBindingContext.class, true); assert sub != null : "SAMLBindingContext"; sub.setRelayState(requestedPath); } return CompletableFuture.completedFuture(null); }
ArmeriaServerHttpRequest(ServiceRequestContext ctx, HttpRequest req, DataBufferFactoryWrapper<?> factoryWrapper) { super(URI.create(requireNonNull(req, "req").path()), null, fromArmeriaHttpHeaders(req.headers())); this.ctx = requireNonNull(ctx, "ctx"); this.req = req; body = Flux.from(req).cast(HttpData.class).map(factoryWrapper::toDataBuffer) // Guarantee that the context is accessible from a controller method // when a user specify @RequestBody in order to convert a request body into an object. .publishOn(Schedulers.fromExecutor(ctx.contextAwareExecutor())); }
@Override public CompletionStage<Void> beforeInitiatingSso(ServiceRequestContext ctx, HttpRequest req, MessageContext<AuthnRequest> message, SamlIdentityProviderConfig idpConfig) { message.getSubcontext(SAMLBindingContext.class, true) .setRelayState(req.path()); return CompletableFuture.completedFuture(null); }
Mono<Void> handle(ServiceRequestContext ctx, HttpRequest req, CompletableFuture<HttpResponse> future, @Nullable String serverHeader) { final ArmeriaServerHttpRequest convertedRequest; try { convertedRequest = new ArmeriaServerHttpRequest(ctx, req, factoryWrapper); } catch (Exception e) { logger.warn("{} Invalid request path: {}", ctx, req.path(), e); future.complete(HttpResponse.of(HttpStatus.BAD_REQUEST)); return Mono.empty(); } final ArmeriaServerHttpResponse convertedResponse = new ArmeriaServerHttpResponse(ctx, future, factoryWrapper, serverHeader); return httpHandler.handle(convertedRequest, convertedResponse) .doOnSuccessOrError((unused, cause) -> { if (cause != null) { logger.debug("{} Failed to handle a request", ctx, cause); convertedResponse.setComplete(cause).subscribe(); } else { convertedResponse.setComplete().subscribe(); } }); } }
private HttpResponse execute(@Nullable EventLoop eventLoop, HttpRequest req) { final String concatPaths = concatPaths(uri().getRawPath(), req.path()); req.path(concatPaths); final PathAndQuery pathAndQuery = PathAndQuery.parse(concatPaths); if (pathAndQuery == null) { req.abort(); return HttpResponse.ofFailure(new IllegalArgumentException("invalid path: " + concatPaths)); } return execute(eventLoop, req.method(), pathAndQuery.path(), pathAndQuery.query(), null, req, (ctx, cause) -> { if (ctx != null && !ctx.log().isAvailable(RequestLogAvailability.REQUEST_START)) { // An exception is raised even before sending a request, so abort the request to // release the elements. req.abort(); } return HttpResponse.ofFailure(cause); }); }
@Override public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception { final SamlServiceFunction func = serviceMap.get(req.path()); if (func == null) { return HttpResponse.of(HttpStatus.BAD_REQUEST); } final CompletionStage<AggregatedHttpMessage> f; if (portConfigHolder.isDone()) { f = req.aggregate(); } else { f = portConfigHolder.future().thenCompose(unused -> req.aggregate()); } return HttpResponse.from(f.handle((msg, cause) -> { if (cause != null) { return HttpResponse.of(HttpStatus.BAD_REQUEST); } final SamlPortConfig portConfig = portConfigHolder.config().get(); if (portConfig.scheme().isTls() != ctx.sessionProtocol().isTls()) { return HttpResponse.of(HttpStatus.BAD_REQUEST); } // Use user-specified hostname if it exists. // If there's no hostname set by a user, the default virtual hostname will be used. final String defaultHostname = firstNonNull(sp.hostname(), ctx.virtualHost().defaultHostname()); return func.serve(ctx, msg, defaultHostname, portConfig); })); }
@Override public HttpResponse execute(ClientRequestContext ctx, HttpRequest req) throws Exception { if (!isValidPath(req)) { final IllegalArgumentException cause = new IllegalArgumentException("invalid path: " + req.path()); handleEarlyRequestException(ctx, req, cause); return HttpResponse.ofFailure(cause); } final Endpoint endpoint = ctx.endpoint().resolve(ctx) .withDefaultPort(ctx.sessionProtocol().defaultPort()); final EventLoop eventLoop = ctx.eventLoop(); final DecodedHttpResponse res = new DecodedHttpResponse(eventLoop); if (endpoint.hasIpAddr()) { // IP address has been resolved already. acquireConnectionAndExecute(ctx, endpoint, endpoint.ipAddr(), req, res); } else { // IP address has not been resolved yet. final Future<InetSocketAddress> resolveFuture = addressResolverGroup.getResolver(eventLoop) .resolve(InetSocketAddress.createUnresolved(endpoint.host(), endpoint.port())); if (resolveFuture.isDone()) { finishResolve(ctx, endpoint, resolveFuture, req, res); } else { resolveFuture.addListener( (FutureListener<InetSocketAddress>) future -> finishResolve(ctx, endpoint, future, req, res)); } } return res; }
@Override public CompletionStage<Void> beforeInitiatingSso(ServiceRequestContext ctx, HttpRequest req, MessageContext<AuthnRequest> message, SamlIdentityProviderConfig idpConfig) { final String requestedPath = req.path(); if (requestedPath.length() <= 80) { // Relay the requested path by default. final SAMLBindingContext sub = message.getSubcontext(SAMLBindingContext.class, true); assert sub != null : "SAMLBindingContext"; sub.setRelayState(requestedPath); } return CompletableFuture.completedFuture(null); }
@Override public CompletionStage<Void> beforeInitiatingSso(ServiceRequestContext ctx, HttpRequest req, MessageContext<AuthnRequest> message, SamlIdentityProviderConfig idpConfig) { final QueryStringDecoder decoder = new QueryStringDecoder(req.path(), true); final List<String> ref = decoder.parameters().get("ref"); if (ref == null || ref.isEmpty()) { return CompletableFuture.completedFuture(null); } final String relayState = ref.get(0); if (idpConfig.ssoEndpoint().bindingProtocol() == SamlBindingProtocol.HTTP_REDIRECT && relayState.length() > 80) { return CompletableFuture.completedFuture(null); } final SAMLBindingContext sub = message.getSubcontext(SAMLBindingContext.class, true); assert sub != null : SAMLBindingContext.class.getName(); sub.setRelayState(relayState); return CompletableFuture.completedFuture(null); }
@Override public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception { final SamlServiceFunction func = serviceMap.get(req.path()); if (func == null) { return HttpResponse.of(HttpStatus.BAD_REQUEST); } final CompletionStage<AggregatedHttpMessage> f; if (portConfigHolder.isDone()) { f = req.aggregate(); } else { f = portConfigHolder.future().thenCompose(unused -> req.aggregate()); } return HttpResponse.from(f.handle((msg, cause) -> { if (cause != null) { return HttpResponse.of(HttpStatus.BAD_REQUEST); } final SamlPortConfig portConfig = portConfigHolder.config().get(); if (portConfig.scheme().isTls() != ctx.sessionProtocol().isTls()) { return HttpResponse.of(HttpStatus.BAD_REQUEST); } // Use user-specified hostname if it exists. // If there's no hostname set by a user, the default virtual hostname will be used. final String defaultHostname = firstNonNull(sp.hostname(), ctx.virtualHost().defaultHostname()); return func.serve(ctx, msg, defaultHostname, portConfig); })); }