User Script

Hello HTTP allows the use of custom script to perform a limited set of operations that are not possible or difficult to do via the UI. The supported programming language is Kotlite, a subset of the Common variant of the Kotlin 1.9 script language. Script means it does not require a main function and the statements at the outermost scope will be executed sequentially.

It is not quite possible to do anything harmful by user scripts, because both the language and the APIs available to be used are limited. For example, it is not possible to make another HTTP request directly from the script, nor modify the URL of the current script, nor execute system commands. There is also a short time limit on execution.

An example use case of user scripts is to generate some hash or signature with some encryption keys and embed into a request before sending it.

Providing custom files for user script use

Files can be imported into an Environment to be consumed by user script. Only small files can be imported. They would be included into data dump files.

User Files

Names can be changed after importing.

Pre-flight Script

Custom pre-flight script can be provided to a request example. It would be executed before firing the request.

It is only available for:

  • Plain/RESTful HTTP requests
  • GraphQL requests

Similar to other request example properties, the script in the "Base" example can be overridden by other request examples.

Pre-flight Script

The only supported mutation operations are:

  • append headers
  • append query parameters

All APIs in the standard library can be used.

In additional, below inputs and APIs are available as follow.

Global Properties

/**
 * Request object.
 * 
 * @param <BODY> One of `Nothing`, `StringBodyClass`, `FormUrlEncodedBodyClass`, `MultipartBodyClass`, `FileBodyClass`, `GraphqlBodyClass`.
 */
val request: MutableRequest<BODY>

/**
 * The environment chosen to be active. Null if there is none.
 */
val environment: Environment?

Types

Request

class Request<BODY>

val Request<*>.url: String
val Request<*>.method: String
val Request<*>.headers: List<Pair<String, String>>
val Request<*>.queryParameters: List<Pair<String, String>>
val <BODY> Request<BODY>.body: BODY?

/**
 * Get a properly encoded URI embedded with query parameters.
 */
fun Request<*>.getResolvedUri(): String

/**
 * Get variables merged from the selected environment, the base request example and the selected request example.
 */
fun Request<*>.getApplicableVariables(): Map<String, String>

MutableRequest

class MutableRequest<BODY> : Request<BODY>

fun MutableRequest<*>.addHeader(key: String, value: String)
fun MutableRequest<*>.addQueryParameter(key: String, value: String)

Environment

class Environment

val Environment.name: String

/**
 * Environment variables. Only enabled variables are available.
 */
val Environment.variables: List<UserKeyValuePair>

/**
 * User files. Only enabled user files are available.
 */
val Environment.userFiles: List<ImportedFile>

UserKeyValuePair

class UserKeyValuePair

val UserKeyValuePair.key: String
val UserKeyValuePair.value: String

/**
 * Either "String" or "File".
 */
val UserKeyValuePair.valueType: String

/**
 * If valueType is "String", return the bytes of the String value.
 * If valueType is "File", return the bytes of the underlying file, or null if no file is selected. Exception would be thrown if a file is specified and cannot be read.
 */
fun UserKeyValuePair.readValueBytes(): ByteArray?

StringBody

class StringBody

val StringBody.value: String

FormUrlEncodedBody

class FormUrlEncodedBody

val FormUrlEncodedBody.value: List<UserKeyValuePair>

MultipartBody

class MultipartBody

val MultipartBody.value: List<UserKeyValuePair>

FileBody

class FileBody

val FileBody.filePath: String?

/**
 * Return the bytes of the underlying file, or null if no file is selected. Exception would be thrown if a file is specified and cannot be read.
 */
val FileBody.readBytes(): ByteArray?

GraphqlBody

class GraphqlBody

val GraphqlBody.document: String
val GraphqlBody.variables: String
val GraphqlBody.operationName: String?

ImportedFile

class ImportedFile

val ImportedFile.name: String
val ImportedFile.originalFilename: String
val ImportedFile.createdWhen: KInstant
val ImportedFile.content: ByteArray

PublicKey

class PublicKey

PrivateKey

class PrivateKey

SecretKey

class SecretKey

Extensions

Encoding

fun ByteArray.encodeToBase64String(): String
fun ByteArray.encodeToBase64UrlString(): String
fun ByteArray.encodeToHexString(): String

fun String.decodeBase64StringToByteArray(): ByteArray
fun String.decodeBase64UrlStringToByteArray(): ByteArray
fun String.decodeHexStringToByteArray(): ByteArray

fun String.decodeJsonStringToMap(): Map<Any?, Any?>

Crypto

fun ByteArray.toSha1Hash(): ByteArray
fun ByteArray.toSha256Hash(): ByteArray
fun ByteArray.toSha512Hash(): ByteArray
fun ByteArray.toMd5Hash(): ByteArray
fun ByteArray.toSha1WithRsaSignature(rsaPrivateKey: PrivateKey): ByteArray
fun ByteArray.toSha256WithRsaSignature(rsaPrivateKey: PrivateKey): ByteArray

fun ByteArray.toPkcs8RsaPublicKey(): PublicKey
fun ByteArray.toPkcs8RsaPrivateKey(): PrivateKey
fun ByteArray.toAesSecretKey(): SecretKey

/**
 * Example value of parameter `algorithm`: "AES/CBC/PKCS5Padding"
 */
fun ByteArray.asEncrypted(algorithm: String, key: SecretKey, iv: ByteArray? = null): ByteArray
fun ByteArray.asDecrypted(algorithm: String, key: SecretKey, iv: ByteArray? = null): ByteArray

Powered by Doctave