All Downloads are FREE. Search and download functionalities are using the official Maven repository.

yakworks.rest.client.OkHttpRestTrait.groovy Maven / Gradle / Ivy

The newest version!
/*
* Copyright 2020 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License")
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
package yakworks.rest.client

import java.util.concurrent.TimeUnit

import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic

import org.jetbrains.annotations.NotNull
import org.springframework.beans.factory.annotation.Value

import okhttp3.Call
import okhttp3.Callback
import okhttp3.Credentials
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
import okhttp3.internal.http.HttpMethod
import yakworks.json.groovy.JsonEngine

/**
 * Trait with helper methods to wrap OKHttps HttpClient for rest api testing
 */
@CompileStatic
//@CompileDynamic
trait OkHttpRestTrait {

    String jsonHeader = "application/json;charset=utf-8"

    @Value('${spring.security.user.name:admin}')
    String username

    @Value('${spring.security.user.password:123}')
    String password

    /**
     * Main method to fire a request and get a response.
     * builds request and executes it with the OkHttpclient.
     * @param method - POST, PUT, GET, DELETE, PATCH, etc..
     * @param uriPath - the path, will call getUrl to append baseUrl if doesnt start with http
     * @param body - the body object to convert to json, usually a Map or sometimes List
     * @return the okhttp response
     */
    Response execute(String method, String uriPath, Object body = null){
        Request request = getRequestBuilder(uriPath)
            .method(method, getRequestBody(method, body))
            .build()
        return getHttpClient().newCall(request).execute()
    }

    void enqueue(String method, String uriPath, Object body = null){
        Request request = getRequestBuilder(uriPath)
            .method(method, getRequestBody(method, body))
            .build()

        getHttpClient().newCall(request).enqueue(
            new EmptyCallBack()
        );
    }

    static class EmptyCallBack implements Callback{
        @Override
        void onFailure(@NotNull Call call, @NotNull IOException e) {
        }
        @Override
        void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
        }
    }
    /**
     * build and OkHttpClient with higher time out of 120
     */
    OkHttpClient getHttpClient(){
        //increase timeout to 120 from 10 so we can debug without socketTimeout
        new OkHttpClient.Builder().readTimeout(120, TimeUnit.SECONDS).build()
    }

    /**
     * converts body object to json and creates a RequestBody
     */
    RequestBody getRequestBody(String method, Object body){
        //do some shenanagans so that we return empty body when POST or PUT
        if(body == null && HttpMethod.requiresRequestBody(method)){
            return RequestBody.create("", null)
        } else if(body == null){
            //on GET and DELETE no body is allowed.
            return null
        } else {
            String jsonBody = toJson(body)
            return RequestBody.create(jsonBody, MediaType.parse(jsonHeader))
        }
    }

    /**
     * creates a Request Builder with content-type header set
     * and Authorization header if field is set
     */
    Request.Builder getRequestBuilder(String uriPath){
        Request.Builder bldr = new Request.Builder()
            .url(getUrl(uriPath))
            .addHeader("Content-Type", jsonHeader)

        if(OkAuth.TOKEN) bldr.addHeader("Authorization", "Bearer ${OkAuth.TOKEN}")

        return bldr
    }

    @CompileDynamic
    String getBaseUrl(){
        //serverPort is provided by the test, spring auto assigns it.
        return "http://localhost:$serverPort"
    }

    String getUrl(String uriPath){
        return uriPath.startsWith('http') ? uriPath : "${getBaseUrl()}$uriPath"
    }

    MediaType getJsonMediaType(){
        MediaType.parse(jsonHeader)
    }

    //POST test
    Response post(String uriPath, Object body) {
        return execute("POST", uriPath, body)
    }

    //PUT
    Response put(String uriPath, Map body, Object id) {
        put("$uriPath/$id", body)
    }

    Response put(String uriPath, Object body) {
        return execute("PUT", uriPath, body)
    }

    Response get(String uriPath, Object id) {
        return get("$uriPath/$id")
    }

    Response get(String uriPath) {
        return execute("GET", uriPath)
    }

    Response delete(String uriPath, Object id) {
        delete("$uriPath/$id")
    }

    Response delete(String uriPath) {
        return execute("DELETE", uriPath)
    }

    /**
     * login with @Value injected username and password if not already
     */
    String login() {
        if(!OkAuth.TOKEN) login(getUsername(), getPassword())
        return OkAuth.TOKEN
    }

    //can override to change the path for getting the oauth token
    String getLoginTokenPath(){
        "api/oauth/token"
    }

    @CompileDynamic
    /** uses the basic auth to login and parse the access_token from response. */
    String login(String uname, String pwd) {
        //create the basic auth credentials
        String basicAuth = Credentials.basic(uname, pwd)
        String lpath = "http://localhost:${serverPort}/${getLoginTokenPath()}"
        Request request = new Request.Builder()
            .url(lpath)
            .addHeader("Authorization", basicAuth)
            .addHeader("Content-Type", jsonHeader)
            .method("POST", RequestBody.create("", null))
            .build()

        Response resp = getHttpClient().newCall(request).execute()
        assert resp.successful
        Map body = bodyToMap(resp)
        OkAuth.TOKEN = body.access_token
        return body.access_token as String
    }

    /**
     * parse the body json to map
     * @param resp the okhttp reponse
     * @return the response body as map
     */
    Map bodyToMap(Response resp){
        JsonEngine.parseJson(resp.body().string(), Map)
    }

    /**
     * parse the body json to list
     */
    List bodyToList(Response resp){
        JsonEngine.parseJson(resp.body().string(), List)
    }

    /**
     * convert the body onject to json strino
     */
    String toJson(Object body){
        JsonEngine.toJson(body)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy