Search in sources :

Example 1 with AuthorizationRequest

use of com.disney.http.auth.AuthorizationRequest in project groovity by disney.

the class Ws method tag.

@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Object tag(Map attributes, Closure body) throws Exception {
    Object url = resolve(attributes, URL);
    if (url == null) {
        throw new RuntimeException("ws() requires 'url' attribute");
    }
    ScriptHelper context = getScriptHelper(body);
    Map variables = context.getBinding().getVariables();
    URI uri;
    URIBuilder builder;
    ArrayList<Header> headers;
    Function handlerFunction;
    Optional<UserPass> userPass;
    Optional<HttpSignatureSigner> signer;
    final AtomicReference openMessage = new AtomicReference<>();
    try {
        builder = new URIBuilder(url.toString());
        bind(context, Uri.CURRENT_URI_BUILDER, builder);
        headers = new ArrayList<Header>();
        bind(context, com.disney.groovity.tags.Header.CURRENT_LIST_FOR_HEADERS, headers);
        Credentials.acceptCredentials(variables);
        Signature.acceptSigner(variables);
        Object oldOut = get(context, OUT);
        StringWriter sw = new StringWriter();
        Object rval = null;
        bind(context, OUT, sw);
        try {
            rval = body.call();
            if (rval instanceof Writable) {
                ((Writable) rval).writeTo(sw);
            }
        } finally {
            bind(context, OUT, oldOut);
            userPass = Credentials.resolveCredentials(variables);
            signer = Signature.resolveSigner(variables);
        }
        String val = sw.toString().trim();
        if (val.length() > 0) {
            openMessage.set(val);
        } else if (rval != null) {
            openMessage.set(rval);
        }
        uri = builder.build();
        handlerFunction = (Function) get(body, Handler.HANDLER_BINDING);
    } catch (URISyntaxException e1) {
        throw new RuntimeException("Invalid URI " + url, e1);
    } finally {
        unbind(context, Uri.CURRENT_URI_BUILDER);
        unbind(context, com.disney.groovity.tags.Header.CURRENT_LIST_FOR_HEADERS);
        unbind(context, Handler.HANDLER_BINDING);
    }
    final Closure closer = resolve(attributes, CLOSE, Closure.class);
    final Closure errorHandler = resolve(attributes, ERROR, Closure.class);
    final Class messageFormat = resolve(attributes, MESSAGE, Class.class);
    final Integer timeout = resolve(attributes, TIMEOUT, Integer.class);
    final AtomicReference<WebSocket> socket = new AtomicReference<>();
    ClientEndpointConfig.Builder configBuilder = ClientEndpointConfig.Builder.create();
    Session session;
    try {
        session = getContainer().connectToServer(new Endpoint() {

            @Override
            public void onOpen(Session session, EndpointConfig config) {
                try {
                    openCount.incrementAndGet();
                    if (timeout != null) {
                        session.setMaxIdleTimeout(timeout * 1000);
                    }
                    WebSocket ws = new WebSocket(session);
                    socket.set(ws);
                    ws.setName(uri.toString());
                    if (handlerFunction != null) {
                        ws.setMessageHandler(arg -> {
                            synchronized (handlerFunction) {
                                handlerFunction.apply(arg);
                            }
                        }, messageFormat);
                    }
                    if (openMessage.get() != null) {
                        ws.call(openMessage.get());
                    }
                } catch (Exception e) {
                    log.log(Level.SEVERE, "Error opening web socket session " + uri, e);
                }
            }

            @Override
            public void onClose(Session session, CloseReason reason) {
                try {
                    closeCount.incrementAndGet();
                    openSessions.remove(session);
                    if (closer != null) {
                        if (closer.getMaximumNumberOfParameters() > 0) {
                            closer.call(reason);
                        } else {
                            closer.call();
                        }
                    }
                } catch (Exception e) {
                    log.log(Level.SEVERE, "Error closing web socket session " + uri, e);
                }
            }

            @Override
            public void onError(Session session, Throwable th) {
                try {
                    errorCount.incrementAndGet();
                    if (errorHandler == null) {
                        throw th;
                    }
                    errorHandler.call(th);
                } catch (Throwable e) {
                    Level logLevel = Level.WARNING;
                    if (th != e) {
                        log.log(logLevel, "Error handling error for web socket session " + uri, e);
                    } else if (th instanceof IOException) {
                        logLevel = Level.FINE;
                    }
                    log.log(logLevel, "WebSocket client error: " + uri, th);
                }
            }
        }, configBuilder.configurator(new ClientEndpointConfig.Configurator() {

            public void beforeRequest(Map<String, List<String>> reqHeaders) {
                // copy programmatic headers
                for (Header header : headers) {
                    List<String> hl = reqHeaders.get(header.getName());
                    if (hl == null) {
                        hl = new ArrayList<>();
                        reqHeaders.put(header.getName(), hl);
                    }
                    hl.add(header.getValue());
                }
                Map<String, Map<String, String>> allChallenges = null;
                if (userPass.isPresent() || signer.isPresent()) {
                    allChallenges = getChallenges(uri, reqHeaders);
                }
                if (userPass.isPresent()) {
                    UserPass user = userPass.get();
                    if (allChallenges != null) {
                        List<String> auths = reqHeaders.get(AUTHORIZATION_HEADER);
                        if (auths == null) {
                            auths = new ArrayList<>();
                            reqHeaders.put(AUTHORIZATION_HEADER, auths);
                        }
                        if (allChallenges.containsKey("basic")) {
                            StringBuilder authBuilder = new StringBuilder(user.getUser());
                            authBuilder.append(":");
                            char[] pass = user.getPass();
                            for (char c : pass) {
                                authBuilder.append(c);
                            }
                            try {
                                auths.add("Basic " + printBase64Binary(authBuilder.toString().getBytes("UTF-8")));
                            } catch (UnsupportedEncodingException e) {
                                log.severe(e.getMessage());
                            }
                        }
                        if (allChallenges.containsKey("digest")) {
                            final String digestUri = uri.getPath() + ((uri.getRawQuery() != null) ? "?" + uri.getRawQuery() : "");
                            Map<String, String> digestChallenge = allChallenges.get("digest");
                            if (log.isLoggable(Level.FINE)) {
                                log.fine("Generating digest auth for " + digestChallenge.toString());
                            }
                            DigestAuthorization digestAuth = new DigestAuthorization();
                            digestAuth.setUsername(user.getUser());
                            digestAuth.setQop("auth");
                            digestAuth.setCnonce(String.valueOf(ThreadLocalRandom.current().nextLong(10000000, 999999999999l)));
                            digestAuth.setNonceCount("000001");
                            digestAuth.setUri(digestUri);
                            for (Entry<String, String> entry : digestChallenge.entrySet()) {
                                String k = entry.getKey();
                                String v = entry.getValue();
                                if ("nonce".equalsIgnoreCase(k)) {
                                    digestAuth.setNonce(v);
                                } else if ("realm".equalsIgnoreCase(k)) {
                                    digestAuth.setRealm(v);
                                } else if ("opaque".equalsIgnoreCase(k)) {
                                    digestAuth.setOpaque(v);
                                }
                            }
                            String signingString;
                            try {
                                signingString = digestAuth.generateSigningString(user.getUser(), new String(user.getPass()), new AuthorizationRequest() {

                                    @Override
                                    public String getURI() {
                                        return digestUri;
                                    }

                                    @Override
                                    public String getMethod() {
                                        return "GET";
                                    }

                                    @Override
                                    public List<String> getHeaders(String name) {
                                        return reqHeaders.get(name);
                                    }
                                });
                                MessageDigest md5 = MessageDigest.getInstance("MD5");
                                digestAuth.setDigest(md5.digest(signingString.toString().getBytes()));
                                if (log.isLoggable(Level.FINE)) {
                                    log.fine("Generated digest auth " + digestAuth.toString());
                                }
                                auths.add(digestAuth.toString());
                            } catch (NoSuchAlgorithmException e) {
                                log.severe("Missing MD5 " + e.getMessage());
                            }
                        }
                    }
                }
                if (signer.isPresent()) {
                    if (allChallenges.containsKey("signature")) {
                        HttpSignatureSigner sig = signer.get();
                        HttpGet signReq = createRequest(uri, reqHeaders);
                        List<Header> beforeHeaders = Arrays.asList(signReq.getAllHeaders());
                        try {
                            sig.process(signReq, null);
                        } catch (HttpException | IOException e) {
                            log.log(Level.SEVERE, "Error processing http signature", e);
                        }
                        Header[] afterHeaders = signReq.getAllHeaders();
                        for (Header h : afterHeaders) {
                            if (!beforeHeaders.contains(h)) {
                                List<String> hl = reqHeaders.get(h.getName());
                                if (hl == null) {
                                    hl = new ArrayList<>();
                                    reqHeaders.put(h.getName(), hl);
                                }
                                hl.add(h.getValue());
                                if (log.isLoggable(Level.FINE)) {
                                    log.fine("Copied HTTP signature header " + h);
                                }
                            }
                        }
                    }
                }
            }
        }).build(), uri);
    } catch (Exception e) {
        errorCount.incrementAndGet();
        throw e;
    }
    openSessions.add(session);
    String var = resolve(attributes, VAR, String.class);
    if (var != null) {
        context.getBinding().setVariable(var, socket.get());
    }
    return socket.get();
}
Also used : AuthorizationRequest(com.disney.http.auth.AuthorizationRequest) Writable(groovy.lang.Writable) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Endpoint(javax.websocket.Endpoint) CloseReason(javax.websocket.CloseReason) MessageDigest(java.security.MessageDigest) UnsupportedEncodingException(java.io.UnsupportedEncodingException) URIBuilder(org.apache.http.client.utils.URIBuilder) Header(org.apache.http.Header) Level(java.util.logging.Level) ScriptHelper(com.disney.groovity.util.ScriptHelper) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) LinkedHashMap(java.util.LinkedHashMap) Closure(groovy.lang.Closure) HttpGet(org.apache.http.client.methods.HttpGet) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) Function(java.util.function.Function) StringWriter(java.io.StringWriter) HttpSignatureSigner(com.disney.http.auth.client.signer.HttpSignatureSigner) HttpException(org.apache.http.HttpException) ClientEndpointConfig(javax.websocket.ClientEndpointConfig) DigestAuthorization(com.disney.http.auth.DigestAuthorization) UserPass(com.disney.groovity.tags.Credentials.UserPass) AtomicReference(java.util.concurrent.atomic.AtomicReference) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) HttpException(org.apache.http.HttpException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) WebSocket(com.disney.groovity.util.WebSocket) ClientEndpointConfig(javax.websocket.ClientEndpointConfig) EndpointConfig(javax.websocket.EndpointConfig) Session(javax.websocket.Session)

Aggregations

UserPass (com.disney.groovity.tags.Credentials.UserPass)1 ScriptHelper (com.disney.groovity.util.ScriptHelper)1 WebSocket (com.disney.groovity.util.WebSocket)1 AuthorizationRequest (com.disney.http.auth.AuthorizationRequest)1 DigestAuthorization (com.disney.http.auth.DigestAuthorization)1 HttpSignatureSigner (com.disney.http.auth.client.signer.HttpSignatureSigner)1 Closure (groovy.lang.Closure)1 Writable (groovy.lang.Writable)1 IOException (java.io.IOException)1 StringWriter (java.io.StringWriter)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 URI (java.net.URI)1 URISyntaxException (java.net.URISyntaxException)1 MessageDigest (java.security.MessageDigest)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 Function (java.util.function.Function)1