package com.mcb; import com.mcb.base.SparkFilter; import com.ning.http.client.*; import com.ning.http.client.multipart.FilePart; import spark.utils.StringUtils; import javax.inject.Inject; import javax.servlet.http.HttpServletResponse; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Base64; import java.util.logging.Level; import java.util.stream.Collectors; import static spark.Spark.get; /** * Created by matthewb on 10/14/15. */ public class RePoster extends SparkFilter { @Inject AsyncHttpClientConfig.Builder config; public void setup() { config .setRequestTimeout(this.getCfg().requestTimeout()) .setConnectTimeout(this.getCfg().connectionTimeout()) .setReadTimeout(this.getCfg().readTimeout()); asyncHttpClient = new AsyncHttpClient(config.build()); get("/" + this.getCfg().routeName(), (req, res) -> { log().log(Level.INFO, req.body()); String file = req.queryParams("file"); if (file == null || file == "") { file = this.getCfg().fileToPost(); } Path toPost = Paths.get(file); if (!Files.exists(toPost)) { log().warning("no content to be processed; check if the file: " + this.getCfg().fileToPost() + " exists and is readable."); res.status(HttpServletResponse.SC_NO_CONTENT); } else { String url = req.queryParams("post_url"); if (url == null || url == "") { url = this.getCfg().remoteUrl(); } String authHeaderName = this.getAuthHeaderName(); ListenableFuture<Response> future = null; if(req.params().containsKey(authHeaderName)) { String authHeaderValue = req.queryParams(authHeaderName); if(!StringUtils.isEmpty(this.getAuthHeaderRename())){ authHeaderName = this.getAuthHeaderRename(); } future = postIt(toPost, url, authHeaderName, authHeaderValue); }else{ future = postIt(toPost, url); } if (future != null) { Response r = future.get(); r.getCookies().stream().map(cookie -> { res.cookie(cookie.getName(), cookie.getValue()); return res; }); r.getHeaders().keySet().stream() .map(h -> { String v = r.getHeaders(h).stream().map(hv -> hv) .collect(Collectors.joining("; ")); res.header(h, v); return res; }); res.status(200); res.body(r.getResponseBody()); res.type(r.getContentType()); if (r.getStatusCode() == this.getCfg().remoteStatusExpected()) { log().info(r.getResponseBody()); res.status(200); } else { log().warning(r.getResponseBody()); res.status(r.getStatusCode()); } return res.body(); } } return ""; }); } AsyncHttpClient asyncHttpClient; /*** * Returns the name of the Authorization header * * @return String name of the Authorization Header */ private String getAuthHeaderName() { return this.getCfg().remoteAuthHeaderName(); } /*** * Returns a Credential to be used in a designated Authorization header * <p> * TODO: implement other Auth types * * @return String value of the Authorization Header */ private String getAuthHeaderValue() { return this.getCfg().remoteAuthHeaderValue(); } private String getAuthHeaderRename() { return this.getCfg().remoteAuthHeaderRename(); } /*** * Returns a Credential to be used in a designated Authorization header * <p> * TODO: implement other Auth types * * @return @link Realm object for use in Authentication */ private Realm getAuthRealm() { String type = this.getCfg().remoteAuthType(); if (type != null) { if ("BASIC".toLowerCase().equals(type.toLowerCase())) { String user = this.getCfg().remoteAuthUsername(); String pass = this.getCfg().remoteAuthPassword(); String encoded = Base64.getEncoder().encodeToString((user + ':' + pass).getBytes(StandardCharsets.UTF_8)); Realm.RealmBuilder realm = new Realm.RealmBuilder(); realm.setPassword(pass) .setPrincipal(user) .setScheme(Realm.AuthScheme.BASIC) .setUsePreemptiveAuth(true); return realm.build(); } if ("DIGEST".toLowerCase().equals(type.toLowerCase())) { String user = this.getCfg().remoteAuthUsername(); String pass = this.getCfg().remoteAuthPassword(); String encoded = Base64.getEncoder().encodeToString((user + ':' + pass).getBytes(StandardCharsets.UTF_8)); Realm.RealmBuilder realm = new Realm.RealmBuilder(); realm.setPassword(pass) .setPrincipal(user) .setScheme(Realm.AuthScheme.DIGEST) .setUsePreemptiveAuth(true); return realm.build(); } } return null; } /*** * Posts to the indicated url * <p> * TODO: implement other Auth types * * @param @link Path file * @param @link String url * @return a @link ListenableFuture<Response> */ private ListenableFuture<Response> postIt(Path file, String url) { return this.postIt(file, url, null, null); } /*** * Posts to the indicated url * <p> * TODO: implement other Auth types * * @param file * @param authHeaderName * @param authHeaderValue * @return a @link ListenableFuture<Response> */ private ListenableFuture<Response> postIt(Path file, String url, String authHeaderName, String authHeaderValue) { com.ning.http.client.AsyncHttpClient.BoundRequestBuilder builder = asyncHttpClient .preparePost(url) .setRequestTimeout(this.getCfg().requestTimeout()) .addBodyPart(new FilePart(file.getFileName().toString(), file.toFile())); if(!StringUtils.isEmpty(authHeaderName) && !StringUtils.isEmpty(authHeaderValue)) { builder.addHeader(authHeaderName, authHeaderValue); } else { Realm result = this.getAuthRealm(); if(result != null) { builder.setRealm(result); } else if(this.getAuthHeaderValue() != null && this.getAuthHeaderName() != null) { builder.addHeader(this.getAuthHeaderName(), this.getAuthHeaderValue()); } } Realm realm = getAuthRealm(); if (realm != null) { builder.setRealm(realm); } else if (getAuthHeaderValue() != null && getAuthHeaderName() != null) { builder.addHeader(getAuthHeaderName(), getAuthHeaderValue()); } ListenableFuture<Response> result = builder.execute(new AsyncCompletionHandler<Response>() { @Override public Response onCompleted(Response response) throws Exception { return response; } @Override public void onThrowable(Throwable t) { // Something wrong happened. if (log().isLoggable(Level.FINER)) { log().log(Level.WARNING, t.getLocalizedMessage(), t); } else { log().warning(t.getLocalizedMessage()); } } }); return result; } }