HttpRequestPort.kt
package com.hexagonkt.http.model
import com.hexagonkt.core.urlOf
import com.hexagonkt.http.formatQueryString
import java.net.URL
import java.security.cert.X509Certificate
// TODO 'formParameters' are a kind of 'part' and both are handled as part of the 'body'
// they could be handled as a special kind of type in body processing (List<HttpPartPort>)
interface HttpRequestPort : HttpMessage {
val method: HttpMethod // "GET"
val protocol: HttpProtocol // "http"
val host: String // "example.com"
val port: Int // 80
val path: String // "/foo" servlet path + path info
val queryParameters: QueryParameters
val parts: List<HttpPart> // hash of multipart parts
val formParameters: FormParameters
val accept: List<ContentType>
val authorization: Authorization?
val certificateChain: List<X509Certificate>
val contentLength: Long // length of request.body (or 0)
fun with(
body: Any = this.body,
headers: Headers = this.headers,
contentType: ContentType? = this.contentType,
method: HttpMethod = this.method,
protocol: HttpProtocol = this.protocol,
host: String = this.host,
port: Int = this.port,
path: String = this.path,
queryParameters: QueryParameters = this.queryParameters,
parts: List<HttpPart> = this.parts,
formParameters: FormParameters = this.formParameters,
cookies: List<Cookie> = this.cookies,
accept: List<ContentType> = this.accept,
authorization: Authorization? = this.authorization,
certificateChain: List<X509Certificate> = this.certificateChain,
): HttpRequestPort
operator fun plus(header: Header): HttpRequestPort =
with(headers = headers + header)
operator fun plus(queryParameter: QueryParameter): HttpRequestPort =
with(queryParameters = queryParameters + queryParameter)
operator fun plus(part: HttpPart): HttpRequestPort =
with(parts = parts + part)
operator fun plus(formParameter: FormParameter): HttpRequestPort =
with(formParameters = formParameters + formParameter)
operator fun plus(cookie: Cookie): HttpRequestPort =
with(cookies = cookies + cookie)
operator fun plus(headers: Headers): HttpRequestPort =
with(headers = this.headers + headers)
operator fun plus(queryParameters: QueryParameters): HttpRequestPort =
with(queryParameters = this.queryParameters + queryParameters)
operator fun plus(parts: List<HttpPart>): HttpRequestPort =
with(parts = this.parts + parts)
operator fun plus(formParameters: FormParameters): HttpRequestPort =
with(formParameters = this.formParameters + formParameters)
fun certificate(): X509Certificate? =
certificateChain.firstOrNull()
fun partsMap(): Map<String, HttpPart> =
parts.associateBy { it.name }
fun url(): URL =
when {
queryParameters.isEmpty() && port == 80 -> "${protocol.schema}://$host/$path"
queryParameters.isEmpty() -> "${protocol.schema}://$host:$port/$path"
else -> "${protocol.schema}://$host:$port/$path?${formatQueryString(queryParameters)}"
}
.let(::urlOf)
fun userAgent(): String? =
headers["user-agent"]?.value as? String
fun referer(): String? =
headers["referer"]?.value as? String
fun origin(): String? =
headers["origin"]?.value as? String
fun authorization(): Authorization? =
(headers["authorization"]?.value as? String)
?.split(" ", limit = 2)
?.let { Authorization(it.first(), it.last()) }
}