Working with HTTP or HTTPS services

A common use of the Connection API is to work with REST services over HTTP or HTTPS.

The following sections contain additional information regarding the use of the Connection API to work with HTTP and HTTPS services. A more general description of the Connection API can be found in Using the Connection API. For reference information about the http and https connection protocols and their configuration, see HTTP and HTTPS protocols.

Invoking a simple REST service

The following example uses the Connection API and zero.core.Json to POST a simple JSON request to a REST service and deserialize the response:

try {
    // Create Connection object to POST to our target resource
    Connection conn = new Connection("http://localhost:8080/myService.groovy", Connection.Operation.POST);
   
    // Set Content-Type for request body
    conn.addRequestHeader("Content-Type", "text/json; charset=\"UTF-8\"");
   
    // Set request body (requestData is a Map representing the JSON object)
    conn.setRequestBody(Json.encode(requestData)); 

    // Send request and prepare for response
    Connection.Response resp = conn.getResponse();
   
    // Check HTTP status code was 200
    if ("200".equals(resp.getResponseStatus())) {
   
        // Could check response Content-Type here, if necessary
        
        // Get response body and deserialize JSON
        Object resultData = Json.decode(resp.getResponseBodyAsString());
   
        // resultData now contains deserialized JSON response
        
    } else {
    
        // Handle status code other than "200"
        
    }
    
} catch (Exception e) {

    // Handle exception
    
}

Working with Content-Type and character encodings

The Connection API and http and https protocol implementations honor the content encoding specified by the charset parameter of the Content-Type header when converting between character and binary data:

  • When sending a String or Reader object as the response body, the application should add a Content-Type request header with a charset value indicating the encoding to use when writing the character data into the HTTP request. If no charset value is specified, the HTTP default encoding, ISO-8859-1, will be used.
  • When the application requests the response body using getResponseBodyAsString() or getResponseBodyReader() the charset value in the response content type sent by the server will be honored. If no charset value is specified, the HTTP default encoding, ISO-8859-1, will be used.

The following code sample sends a text/plain string using the UTF-8 encoding and obtains a string contain the response. The response is decoded using the response character encoding specified by the server:

try {

    // POST a text/plain body with UTF-8 encoding
    Connection conn = new Connection("http://localhost:8080/myService.groovy", Connection.Operation.POST);
    conn.addRequestHeader("Content-Type", "text/plain; charset=\"UTF-8\"");
    conn.setRequestBody("This string can contain any Unicode character"); 

    // Read response string, using response charset encoding sent by server
    String responseString = conn.getResponse().getResponseBodyAsString();
       
} catch (Exception e) {

    // Handle exception
    
}

Uploading files to HTTP or HTTPS services

The Connection API can be used in conjunction with an instance of the MultipartBody class to upload a file to HTTP or HTTPS services, using the multipart/form-data content type. This can be seen in the following example:

try {

    // Open input stream for image file contents
    InputStream imageStream =
        Connection.doGET("file:///C:/images/uploadImage.jpeg").getResponseInputStream();

    // Prepare multipart request body
    MultipartBody multipartBody = new MultipartBody(MultipartBody.MULTIPART_FORM_DATA);            
    MultipartBody.Part filePart = reqBody.add(imageStream, "image/jpeg");
    filePart.setProperty(MultipartBody.CONTENT_DISPOSITION,
                         "form-data; name=\"myFile\"; filename=\"myFile.jpeg\"");

    // POST multipart form data to HTTP service
    String statusCode = Connection.doPOST("http://localhost:8080/uploadFile.groovy",
                                          multipartBody).getResponseStatus();
    
    // Check HTTP statusCode to confirm successful upload    
    
} catch (Exception e) {

    // Handle exception
    
}

The above example uses two Connection API invocations. The first uses the GET operation and the file protocol to open an InputStream from which the contents of an image file can be read. The second invocation uses the POST operation of the http protocol to send the image file to the HTTP service. The request body for the POST is an instance of zero.core.connection.MultipartBody that contains a single part representing the file. The http and https protocol implementations will perform the appropriate encoding of the request body and send a multipart MIME message to the HTTP service.

See the API reference for zero.core for more information about the zero.core.connection.MultipartBody class.

Targeting local HTTP resources

An application can use the Connection API to invoke a local endpoint relative to the current request path, without specifying the full URL. This mechanism can be used when Connection API is invoked within the context of an incomming HTTP or HTTPS request.

Relative names can be specified using any Connection API method that sets the target resource name. For example, an application can use a relative name when constructing a new Connection object:

    Connection conn = new Connection("./myOtherScript.groovy");

If the above example code is invoked in the request handler for http://myApp.projectzero.org:8080/contextRoot/someFolder/myScript.groovy, the resulting connection will target http://myApp.projectzero.org:8080/contextRoot/someFolder/myOtherScript.groovy. Moreover, the result of conn.getResource() will be the full target resource name and not ./myOtherScript.groovy

The following prefixes can be used to indicate a relative target resource name:

Prefix Description
./ Relative to folder containing current request handler.
../ Relative to parent of folder containing current request handler.
~/ Relative to the application context root.

Any target resource name that does not begin with one of the prefixes indicated above will be interpreted as an absolute resource name. In particular, resources starting with / are not resolved relative to the current request.

Basic authentication and connection configuration

The http and https protocol implementations support a number of protocol configuration parameters, such as HTTPS trust store configuration and request timeout values. Amongst these are the userid and password protocol configuration parameters, which can be used to automatically include a basic authentication header in the outgoing request.

The following example uses the setProtocolConfiguration() method to set programmatically the basic authentication credentials for the request sent to the HTTP service:

try {

    // Create Connection object (default operation is GET)
    Connection conn = new Connection("http://localhost:8080/myService.groovy");

    // Set parameters for basic authentication
    Map<String, Object> parameters = new HashMap<String, Object>();
    parameters.put("userid", "user1");
    parameters.put("password", "password1");
    conn.setProtocolConfiguration("http", parameters);

    // Send request and prepare for response
    Connection.Response resp = conn.getResponse();
    
    // Work with the response
       
} catch (Exception e) {

    // Handle exception
    
}

For circumstances in which it is not be desirable to hard code protocol parameters in the application logic, the connection infrastructure enables protocol configuration to be specified in zero.config. For example, the following connection destination configuration specifies the basic authentication parameters for all requests to the http://localhost:8080/myService.groovy service:

/config/connection/destinations += {
   "http://localhost:8080/myService.groovy" : {
        "connection" : {
            "protocol" : "http",
            "config" : {
                "userid" : "user1",
                "password" : "password1"
            }
        }
    }
}

With the above destination configuration in place, the application can send a request to the service without hard coding the protocol configuration:

try {

    // Create Connection object (default operation is GET)
    Connection conn = new Connection("http://localhost:8080/myService.groovy");

    // Send request and prepare for response
    Connection.Response resp = conn.getResponse();
    
    // Work with the response
       
} catch (Exception e) {

    // Handle exception
    
}

Connection handlers can also set protocol configuration. For example, a connection handler could dynamically select a userid and password value for an outgoing request. As with specifying the configuration in the destination configuration, using a connection handler would avoid any modification of the application logic but would also avoid the restriction of a fixed value in zero.config. For more information about the mechanisms available for protocol configuration, see Configuring protocols.

For more information about the configuration of the http and https connection protocols, including the configuration of the trust store and key store for HTTPS communications, see HTTP and HTTPS protocols.

Version 1.0.0.3.25591