@Override public String getRestxPath() { return original.getRestxPath(); }
@Override public String getBaseNetworkPath() { return original.getBaseNetworkPath(); }
@Override public Optional<String> getHeader(String headerName) { return original.getHeader(headerName); }
private boolean isPreflightRequest(RestxRequest req) { return req.getHeader("Origin").isPresent() && req.getHeader("Access-Control-Request-Method").isPresent() && "OPTIONS".equals(req.getHttpMethod()); }
/** * Prepares the metadata to be used for session stats monitoring. * * If you override this method, make sure to include the map built by the default implementation if you want * the monitor admin session view to work properly, unless you override it too. * * @param req the request for which metadata should be prepared * @param session the session for which metadata should be prepared * @return the prepared metadata */ protected ImmutableMap<String, String> prepareSessionStatsMetadata(RestxRequest req, RestxSession session) { return ImmutableMap.of( "clientAddress", req.getClientAddress(), "userAgent", req.getHeader("User-Agent").or("Unknown")); } }
protected boolean isSimpleCORSRequest(RestxRequest req) { // see https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS if (!SIMPLE_METHODS.contains(req.getHttpMethod())) { return false; } Optional<String> origin = req.getHeader("Origin"); if (!origin.isPresent()) { return false; } if ("POST".equals(req.getHttpMethod())) { if (!asList("application/x-www-form-urlencoded", "multipart/form-data", "text/plain") .contains(req.getContentType())) { return false; } } return true; }
@Override public Optional<RestxHandlerMatch> match(RestxRequest request) { Optional<String> enc = request.getHeader("Accept-Encoding"); if (!enc.isPresent()) { return Optional.absent(); } if (!acceptsGzip(enc.get())) { return Optional.absent(); } for (RestxRequestMatcher matcher : matchers) { Optional<? extends RestxRequestMatch> match = matcher.match(request.getHttpMethod(), request.getRestxPath()); if (match.isPresent()) { return Optional.of(new RestxHandlerMatch(match.get(), this)); } } return Optional.absent(); }
Monitor monitor = metrics.timer("<HTTP> " + restxRequest.getHttpMethod() + " " + restxRequest.getRestxPath()).time(); try { Optional<RestxRouting.Match> m = routing.match(restxRequest); String path = restxRequest.getRestxPath(); StringBuilder sb = new StringBuilder() .append("no restx route found for ") .append(restxRequest.getHttpMethod()).append(" ").append(path).append("\n"); if (hasApiDocs()) { sb.append("go to ").append(restxRequest.getBaseUri()).append("/@/ui/api-docs/") .append(" for API documentation\n\n"); out.print(sb.toString()); } else { MDC.put("restx.path", restxRequest.getRestxPath()); MDC.put("restx.method", restxRequest.getHttpMethod()); restxResponse.setContentType("text/plain"); PrintWriter out = restxResponse.getWriter(); if (restxRequest.getContentStream() instanceof BufferedInputStream) { try { JsonLocation location = ex.getLocation(); restxRequest.getContentStream().reset(); out.println(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, ex.getClass().getSimpleName()) + "." + " Please verify your input:"); List<String> lines = CharStreams.readLines( new InputStreamReader(restxRequest.getContentStream())); if ("application/x-www-form-urlencoded".equalsIgnoreCase(restxRequest.getContentType())) {
@Override public Optional<RestxHandlerMatch> match(RestxRequest req) { String path = req.getRestxPath(); return RestxHandlerMatch.of(matcher.match(req.getHttpMethod(), path), this); }
@Override public Optional<RestxHandlerMatch> match(RestxRequest req) { Optional<String> authorization = req.getHeader("Authorization"); if (authorization.isPresent()) { if (authorization.get().toLowerCase(Locale.ENGLISH).startsWith("basic ")) { return Optional.of(new RestxHandlerMatch( new StdRestxRequestMatch("*", req.getRestxPath()), basicHandler)); } else { logger.warn("unsupported authentication type: " + authorization.get()); } } return Optional.absent(); }
Iterable<WhenHttpRequest> findWhensMatchingRequest(ImmutableMap<String, RestxSpec> allSpecs, RestxRequest restxRequest) { Collection<WhenHttpRequest> matchingRequestsSpecs = Lists.newArrayList(); for (Map.Entry<String, RestxSpec> spec : allSpecs.entrySet()) { for (When when : spec.getValue().getWhens()) { if (when instanceof WhenHttpRequest) { WhenHttpRequest request = (WhenHttpRequest) when; String requestPath = request.getPath(); if (!requestPath.startsWith("/")) { requestPath = "/" + requestPath; } StdRequest stdRequest = StdRequest.builder() .setBaseUri("http://restx.io") // baseUri is required but we won't use it .setHttpMethod(request.getMethod()).setFullPath(requestPath).build(); if (restxRequest.getHttpMethod().equals(stdRequest.getHttpMethod()) && restxRequest.getRestxPath().equals(stdRequest.getRestxPath())) { MapDifference<String, ImmutableList<String>> difference = Maps.difference(restxRequest.getQueryParams(), stdRequest.getQueryParams()); if (difference.entriesOnlyOnRight().isEmpty() && difference.entriesDiffering().isEmpty()) { matchingRequestsSpecs.add(request); break; } } } } } return matchingRequestsSpecs; } }
@Override public Optional<RestxHandlerMatch> match(RestxRequest req) { try { HttpServletRequest httpServletRequest = req.unwrap(HttpServletRequest.class); if (httpServletRequest.getUserPrincipal() != null) { return Optional.of(new RestxHandlerMatch( new StdRestxRequestMatch("*", req.getRestxPath()), this)); } else { return Optional.absent(); } } catch (IllegalArgumentException ex) { return Optional.absent(); } catch (NoClassDefFoundError e) { if ("javax/servlet/http/HttpServletRequest".equals(e.getMessage())) { // this may happen when app depends on restx-servlet to have servlet support, but is run outside a servlet container // eg with restx-simple-server. In this case the provided dependency on servlet API (that is provided by // the servlet container when run inside such container) will make us fail with a NoClassDefFoundError return Optional.absent(); } else { throw e; } } }
public RestxSession buildContextFromRequest(RestxRequest req) throws IOException { String restxSessionCookieName = restxSessionCookieDescriptor.getCookieName(); String cookie = req.getCookieValue(restxSessionCookieName).or(""); if (cookie.trim().isEmpty()) { return emptySession; } else { String sig = req.getCookieValue(restxSessionCookieDescriptor.getCookieSignatureName()).or(""); if (!signer.verify(cookie, sig)) { logger.warn("invalid restx session signature. session was: {}. Ignoring session cookie.", cookie); Duration expiration = req.isPersistentCookie(restxSessionCookieName) ? new Duration(DateTime.now(), expires) : Duration.ZERO; ImmutableMap<String, String> valueidsByKey = ImmutableMap.copyOf(entries); String principalName = valueidsByKey.get(RestxPrincipal.SESSION_DEF_KEY); if (principalOptional.isPresent() && permissionFactory.hasRole("restx-admin").has(principalOptional.get(), Collections.<String,String>emptyMap()).isPresent()) { Optional<String> su = req.getHeader("RestxSu"); if (su.isPresent() && !Strings.isNullOrEmpty(su.get())) { try {
Stopwatch stopwatch = Stopwatch.createStarted(); System.out.print("RECORDING REQUEST..."); final String method = restxRequest.getHttpMethod(); final String path = (restxRequest.getRestxUri().length()>1)?restxRequest.getRestxUri().substring(1):restxRequest.getRestxUri(); // remove leading slash final ImmutableMap<String, String> cookies = sessionFilter.toCookiesMap(sessionFilter.buildContextFromRequest(restxRequest)); final byte[] requestBody = ByteStreams.toByteArray(restxRequest.getContentStream()); System.out.println(" >> recorded request " + method + " " + path + " (" + requestBody.length + " bytes) -- " + stopwatch.stop()); recordedSpec.setCapturedRequestSize(requestBody.length);
@Override public Optional<String> getQueryParam(String param) { return original.getQueryParam(param); }
@Override public String getHttpMethod() { return original.getHttpMethod(); }
@Override public <T> T unwrap(Class<T> clazz) { return original.unwrap(clazz); }
@Override public Optional<RestxHandlerMatch> match(RestxRequest request) { Optional<String> enc = request.getHeader("Accept-Encoding"); if (!enc.isPresent()) { return Optional.absent(); } if (!acceptsGzip(enc.get())) { return Optional.absent(); } for (RestxRequestMatcher matcher : matchers) { Optional<? extends RestxRequestMatch> match = matcher.match(request.getHttpMethod(), request.getRestxPath()); if (match.isPresent()) { return Optional.of(new RestxHandlerMatch(match.get(), this)); } } return Optional.absent(); }
Monitor monitor = metrics.timer("<HTTP> " + restxRequest.getHttpMethod() + " " + restxRequest.getRestxPath()).time(); try { Optional<RestxRouting.Match> m = routing.match(restxRequest); String path = restxRequest.getRestxPath(); StringBuilder sb = new StringBuilder() .append("no restx route found for ") .append(restxRequest.getHttpMethod()).append(" ").append(path).append("\n"); if (hasApiDocs()) { sb.append("go to ").append(restxRequest.getBaseUri()).append("/@/ui/api-docs/") .append(" for API documentation\n\n"); out.print(sb.toString()); } else { MDC.put("restx.path", restxRequest.getRestxPath()); MDC.put("restx.method", restxRequest.getHttpMethod()); restxResponse.setContentType("text/plain"); PrintWriter out = restxResponse.getWriter(); if (restxRequest.getContentStream() instanceof BufferedInputStream) { try { JsonLocation location = ex.getLocation(); restxRequest.getContentStream().reset(); out.println(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, ex.getClass().getSimpleName()) + "." + " Please verify your input:"); List<String> lines = CharStreams.readLines( new InputStreamReader(restxRequest.getContentStream())); if ("application/x-www-form-urlencoded".equalsIgnoreCase(restxRequest.getContentType())) {
@Override public Optional<RestxHandlerMatch> match(RestxRequest req) { String path = req.getRestxPath(); return RestxHandlerMatch.of(matcher.match(req.getHttpMethod(), path), this); }