HttpContext: Lightweight HTTP protocol support.
This commit is contained in:
parent
c887a49f8c
commit
db15eb8f88
134
src/main/com/jdbernard/net/HttpContext.groovy
Normal file
134
src/main/com/jdbernard/net/HttpContext.groovy
Normal file
@ -0,0 +1,134 @@
|
||||
/** @author Jonathan Bernard (jdbernard@gmail.com)
|
||||
* @copyright 2013 Jonathan Bernard. */
|
||||
package com.jdbernard.net
|
||||
|
||||
import java.net.Socket
|
||||
import groovy.json.JsonBuilder
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
/** Helper class to perform basic HTTP communication. */
|
||||
public class HttpContext {
|
||||
|
||||
/** The host to which this object will connect. This also affects the
|
||||
* `Host` header in requests. */
|
||||
public String host = 'vbs-test'
|
||||
|
||||
/** The port number.*/
|
||||
public int port = 8000
|
||||
|
||||
/** A cookie value to send in the request. This value will be automatically
|
||||
* set from any `Set-Cookie` header in the request response. */
|
||||
public String cookie
|
||||
|
||||
/** #### makeMessage
|
||||
* Make and return an HTTP request for the given HTTP method and URL. If
|
||||
* `request` is not null, it is expected to be an object which will be
|
||||
* converted to JSON and included as the request body. The `Host`,
|
||||
* `Cookie`, and `Content-Length` headers will be added based on the
|
||||
* `host` and `cookie` fields and the `request` object. */
|
||||
public String makeMessage(String method, String url, def request) {
|
||||
StringBuilder message = new StringBuilder()
|
||||
message.append(method)
|
||||
message.append(" ")
|
||||
message.append(url)
|
||||
message.append(" HTTP/1.1\r\n")
|
||||
|
||||
if (host && port) {
|
||||
message.append("Host: ")
|
||||
message.append(host)
|
||||
message.append(":")
|
||||
message.append(port)
|
||||
message.append("\r\n") }
|
||||
|
||||
if (cookie) {
|
||||
message.append("Cookie: ")
|
||||
message.append(cookie)
|
||||
message.append("\r\n") }
|
||||
|
||||
if (request) {
|
||||
def jsonRequestBuilder = new JsonBuilder(request)
|
||||
String requestBody = jsonRequestBuilder.toString()
|
||||
|
||||
message.append("Content-Length: ")
|
||||
message.append(requestBody.length())
|
||||
message.append("\r\n\r\n")
|
||||
message.append(requestBody) }
|
||||
|
||||
message.append("\r\n")
|
||||
return message.toString()
|
||||
}
|
||||
|
||||
/** #### send
|
||||
* A wrapper around `makeMessage` and `send(String message)` to create a
|
||||
* request, send it, and return the response. */
|
||||
public def send(String method, String url, def request) {
|
||||
return send(makeMessage(method, url, request)) }
|
||||
|
||||
/** #### send
|
||||
* Send a message to the host specified by the object's `host` and `port`
|
||||
* fields and parses the response. Returns an object with the following
|
||||
* properties:
|
||||
*
|
||||
* - `status`: the HTTP response status (200, 404, etc.).
|
||||
* - `headers`: A list of header lines (one line per list entry).
|
||||
* - `content`: the response body (expected as JSON from the server) parsed
|
||||
* into a Groovy object.
|
||||
* - `responseTime`: the time measured immediately after the client flushes
|
||||
* its output buffer to the time it completely reads the server response.
|
||||
*/
|
||||
public def send(String message) {
|
||||
Map result = [headers:[], content: null]
|
||||
Socket sock = new Socket(host, port)
|
||||
def startTime
|
||||
|
||||
sock.withStreams { strin, out ->
|
||||
def writer = new BufferedWriter(new OutputStreamWriter(out))
|
||||
def reader = new BufferedReader(new InputStreamReader(strin))
|
||||
int bytesExpected
|
||||
writer.write(message)
|
||||
startTime = System.currentTimeMillis()
|
||||
writer.flush()
|
||||
|
||||
def line = reader.readLine().trim()
|
||||
result.status = line.split(/\s/)[1]
|
||||
line = reader.readLine().trim()
|
||||
|
||||
while(line) {
|
||||
def m = (line =~ /Content-Length: (\d+)/)
|
||||
if (m) bytesExpected = m[0][1] as int
|
||||
|
||||
m = (line =~ /Set-Cookie: ([^=]+=[^;]+);.+/)
|
||||
if (m) this.cookie = m[0][1]
|
||||
|
||||
result.headers << line
|
||||
line = reader.readLine() }
|
||||
|
||||
if (bytesExpected) {
|
||||
StringBuilder sb = new StringBuilder()
|
||||
for (int i = 0; i < bytesExpected; i++) {
|
||||
sb.append(reader.read() as char) }
|
||||
|
||||
result.responseTime = System.currentTimeMillis() - startTime
|
||||
|
||||
try { result.content = new JsonSlurper().parseText(sb.toString()) }
|
||||
catch (Exception e) { result.content = sb.toString() } }
|
||||
else
|
||||
result.responseTime = System.currentTimeMillis() - startTime
|
||||
}
|
||||
|
||||
sock.close()
|
||||
return result
|
||||
}
|
||||
|
||||
/** #### get
|
||||
* A wrapper to perform a simple `GET` request. This calls
|
||||
* `send(String method, String url, def request)` with `method = "GET"`,
|
||||
* and `request = null`. */
|
||||
public def get(String url) { return send('GET', url, null) }
|
||||
|
||||
/** #### post
|
||||
* A wrapper to perform a `POST` request. This calls
|
||||
* `send(String method, String url, def request)` with `method =
|
||||
* "POST"`. */
|
||||
public def post(String url, def body) { return send('POST', url, body) }
|
||||
}
|
Loading…
Reference in New Issue
Block a user