Skip to content

Commit 1ebe653

Browse files
committed
Request data
1 parent 97b4ece commit 1ebe653

54 files changed

Lines changed: 544 additions & 376 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/src/main/kotlin/net/devslash/BodyProviders.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
package net.devslash
22

33

4-
class BasicBodyProvider(private val body: String, val data: RequestData) : BodyProvider {
4+
class BasicBodyProvider<T>(private val body: String, val data: RequestData<T>) : BodyProvider {
55
fun get(): String {
66
var copy = "" + body
77
data.getReplacements().forEach { (key, value) -> copy = copy.replace(key, value) }
88
return copy
99
}
1010
}
1111

12-
class FormBody(private val body: Map<String, List<String>>,
13-
private val data: RequestData) : BodyProvider {
12+
class FormBody<T>(
13+
private val body: Map<String, List<String>>,
14+
private val data: RequestData<T>
15+
) : BodyProvider {
1416
fun get(): Map<String, List<String>> {
1517
return body.map {
16-
val entries = it.value.map { it.asReplaceableValue().get(data) }
18+
val entries = it.value.map { v -> data.accept(v) }
1719
it.key to entries
1820
}.toMap()
1921
}
@@ -25,7 +27,7 @@ class JsonBody(private val any: Any) : BodyProvider {
2527
}
2628
}
2729

28-
fun getBodyProvider(call: Call, data: RequestData): BodyProvider {
30+
fun <T> getBodyProvider(call: Call<T>, data: RequestData<T>): BodyProvider {
2931
if (call.body == null) {
3032
return EmptyBodyProvider
3133
}

api/src/main/kotlin/net/devslash/CookieJar.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import java.util.concurrent.ConcurrentHashMap
66
class CookieJar : SimpleBeforeHook, SimpleAfterHook {
77
private val cookies = ConcurrentHashMap(mutableMapOf<String, MutableMap<String, String>>())
88

9-
override fun accept(req: HttpRequest, data: RequestData) {
9+
override fun <T> accept(req: HttpRequest, data: RequestData<T>) {
1010
val basicURl = URL(req.url)
1111
val filteredUrl = "${basicURl.protocol}://${basicURl.host}"
1212

api/src/main/kotlin/net/devslash/Definitions.kt

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,26 @@ import kotlinx.coroutines.channels.Channel
44

55
sealed class Value
66
data class StrValue(val value: String) : Value()
7-
data class ProvidedValue(val lambda: (RequestData) -> String) : Value()
7+
data class ProvidedValue<T>(val lambda: (RequestData<T>) -> String) : Value()
88

99
interface BodyProvider
10-
data class Session(val calls: List<Call>, val concurrency: Int = 100, val delay: Long?, val rateOptions: RateLimitOptions)
10+
data class Session(val calls: List<Call<*>>, val concurrency: Int = 100, val delay: Long?, val rateOptions: RateLimitOptions)
1111

12-
data class Call(val url: String,
12+
data class Call<T>(val url: String,
1313
val headers: Map<String, List<Value>>?,
1414
val cookieJar: String?,
1515
val type: HttpMethod,
16-
val dataSupplier: RequestDataSupplier?,
17-
val body: HttpBody?,
16+
val dataSupplier: RequestDataSupplier<T>?,
17+
val body: HttpBody<T>?,
1818
val onError: OnError?,
1919
val beforeHooks: List<BeforeHook>,
2020
val afterHooks: List<AfterHook>)
2121

22-
interface RequestDataSupplier {
22+
interface RequestDataSupplier<T> {
2323
/**
2424
* Request data should be a closure that is safe to call on a per-request basis
2525
*/
26-
suspend fun getDataForRequest(): RequestData?
26+
suspend fun getDataForRequest(): RequestData<T>?
2727

2828
fun init() {
2929
// By default this is empty, but implementors can be assured that on a per-call basis, this
@@ -32,54 +32,58 @@ interface RequestDataSupplier {
3232
}
3333

3434
interface OutputFormat {
35-
fun accept(resp: HttpResponse, rep: RequestData): ByteArray?
35+
fun <T> accept(resp: HttpResponse, rep: RequestData<T>): ByteArray?
3636
}
3737

38-
interface RequestData {
38+
interface RequestData<T> {
39+
@Deprecated("Instead, please migrate to utilising Get")
3940
fun getReplacements(): Map<String, String>
41+
fun get(): T
42+
fun accept(v: String): String
4043
}
4144

4245
interface BasicOutput : FullDataAfterHook
4346

44-
data class HttpBody(val value: String?,
47+
data class HttpBody<T>(val value: String?,
4548
val formData: Map<String, List<String>>?,
4649
val jsonObject: Any?,
47-
val lazyJsonObject: ((RequestData) -> Any)?)
50+
val lazyJsonObject: ((RequestData<T>) -> Any)?)
4851

4952
interface ReplaceableValue<T, V> {
5053
fun get(data: V): T
5154
}
5255

53-
fun String.asReplaceableValue() = object : ReplaceableValue<String, RequestData> {
54-
override fun get(data: RequestData): String {
56+
@Deprecated("Please use accept in request data")
57+
fun String.asReplaceableValue() = object : ReplaceableValue<String, RequestData<List<String>>> {
58+
override fun get(data: RequestData<List<String>>): String {
5559
val replacements = data.getReplacements()
5660
var copy = "" + this@asReplaceableValue
57-
replacements.forEach { key, value -> copy = copy.replace(key, value) }
61+
replacements.forEach { (key, value) -> copy = copy.replace(key, value) }
5862
return copy
5963
}
6064
}
6165

6266
interface BeforeHook
6367

6468
fun (() -> Unit).toPreHook() = object : SimpleBeforeHook {
65-
override fun accept(req: HttpRequest, data: RequestData) {
69+
override fun <T> accept(req: HttpRequest, data: RequestData<T>) {
6670
this@toPreHook()
6771
}
6872
}
6973

7074
interface SessionPersistingBeforeHook : BeforeHook {
71-
suspend fun accept(sessionManager: SessionManager,
75+
suspend fun <T> accept(sessionManager: SessionManager,
7276
cookieJar: CookieJar,
7377
req: HttpRequest,
74-
data: RequestData)
78+
data: RequestData<T>)
7579
}
7680

77-
interface SkipBeforeHook : BeforeHook {
78-
fun skip(requestData: RequestData): Boolean
81+
interface SkipBeforeHook<T> : BeforeHook {
82+
fun skip(requestData: RequestData<T>): Boolean
7983
}
8084

8185
interface SimpleBeforeHook : BeforeHook {
82-
fun accept(req: HttpRequest, data: RequestData)
86+
fun <T> accept(req: HttpRequest, data: RequestData<T>)
8387
}
8488

8589
class Envelope<T>(private val message: T, private val maxRetries: Int = 3) {
@@ -115,8 +119,8 @@ interface ChainReceivingResponseHook : AfterHook {
115119
fun accept(resp: HttpResponse)
116120
}
117121

118-
interface FullDataAfterHook : AfterHook {
119-
fun accept(req: HttpRequest, resp: HttpResponse, data: RequestData)
122+
interface FullDataAfterHook: AfterHook {
123+
fun <T> accept(req: HttpRequest, resp: HttpResponse, data: RequestData<T>)
120124
}
121125

122126
sealed class HttpResult<out T, out E>

api/src/main/kotlin/net/devslash/FetchDsl.kt

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ class UnaryAddBuilder<T> {
2525
data class RateLimitOptions(val enabled: Boolean, val count: Int, val duration: Duration)
2626

2727
@FetchDSL
28-
open class CallBuilder(private val url: String) {
28+
open class CallBuilder<T>(private val url: String) {
29+
2930
private var cookieJar: String? = null
30-
var data: RequestDataSupplier? = null
31-
var body: HttpBody? = null
31+
var data: RequestDataSupplier<T>? = null
32+
var body: HttpBody<T>? = null
3233
var type: HttpMethod = HttpMethod.GET
3334
var headers: Map<String, List<Any>>? = null
34-
var onError: OnError? = RetryOnTransitiveError()
35+
var onError: OnError? = RetryOnTransitiveError<T>()
3536

3637
private var preHooksList = mutableListOf<BeforeHook>()
3738
private var postHooksList = mutableListOf<AfterHook>()
@@ -44,8 +45,8 @@ open class CallBuilder(private val url: String) {
4445
postHooksList.addAll(UnaryAddBuilder<AfterHook>().apply(block).build())
4546
}
4647

47-
fun body(block: BodyBuilder.() -> Unit) {
48-
body = BodyBuilder().apply(block).build()
48+
fun body(block: BodyBuilder<T>.() -> Unit) {
49+
body = BodyBuilder<T>().apply(block).build()
4950
}
5051

5152
private fun mapHeaders(m: Map<String, List<Any>>?): Map<String, List<Value>>? {
@@ -62,7 +63,7 @@ open class CallBuilder(private val url: String) {
6263
}
6364
}
6465

65-
fun build(): Call {
66+
fun build(): Call<T> {
6667
val localHeaders = headers
6768
if (localHeaders == null || !localHeaders.contains("User-Agent")) {
6869
val set = mutableMapOf<String, List<Any>>()
@@ -72,36 +73,38 @@ open class CallBuilder(private val url: String) {
7273
set["User-Agent"] = listOf("FetchDSL (Apache-HttpAsyncClient + Kotlin, version not set)")
7374
headers = set
7475
}
75-
return Call(url, mapHeaders(headers), cookieJar, type, data, body,
76-
onError, preHooksList, postHooksList)
76+
return Call(
77+
url, mapHeaders(headers), cookieJar, type, data, body,
78+
onError, preHooksList, postHooksList
79+
)
7780
}
7881
}
7982

8083
@FetchDSL
81-
class BodyBuilder {
84+
class BodyBuilder<T> {
8285
var value: String? = null
8386
var formParams: Map<String, List<String>>? = null
8487
var jsonObject: Any? = null
85-
var lazyJsonObject: ((RequestData) -> Any)? = null
88+
var lazyJsonObject: ((RequestData<T>) -> Any)? = null
8689

87-
fun build(): HttpBody = HttpBody(value, formParams, jsonObject, lazyJsonObject)
90+
fun build(): HttpBody<T> = HttpBody(value, formParams, jsonObject, lazyJsonObject)
8891
}
8992

9093
@FetchDSL
9194
class MultiCallBuilder {
92-
private var calls = mutableListOf<Call>()
95+
private var calls = mutableListOf<Call<*>>()
9396

94-
fun call(url: String, block: CallBuilder.() -> Unit = {}) {
95-
calls.add(CallBuilder(url).apply(block).build())
97+
fun call(url: String, block: CallBuilder<*>.() -> Unit = {}) {
98+
calls.add(CallBuilder<Any>(url).apply(block).build())
9699
}
97100

98101
fun calls() = calls
99102
}
100103

101104
@FetchDSL
102105
class SessionBuilder {
103-
private var calls = mutableListOf<Call>()
104-
private val chained = mutableListOf<List<Call>>()
106+
private var calls = mutableListOf<Call<*>>()
107+
private val chained = mutableListOf<List<Call<*>>>()
105108

106109
var concurrency = 20
107110
var delay: Long? = null
@@ -113,18 +116,14 @@ class SessionBuilder {
113116
rateOptions = RateLimitOptions(true, count, duration)
114117
}
115118

116-
fun call(url: String, block: CallBuilder.() -> Unit = {}) {
117-
calls.add(CallBuilder(url).apply(block).build())
119+
@JvmName("nonStringCall")
120+
fun <T> call(url: String, block: CallBuilder<T>.() -> Unit = {}) {
121+
calls.add(CallBuilder<T>(url).apply(block).build())
118122
}
119123

120-
// TODO: Re-enable when chaining is stable
121-
// fun chained(block: MultiCallBuilder.(prev: Previous?) -> Unit = {}) {
122-
// if (chained.isNotEmpty()) {
123-
// val line = chained.last().line
124-
//
125-
// }
126-
// chained.add(MultiCallBuilder().apply(block).calls())
127-
// }
124+
fun call(url: String, block: CallBuilder<List<String>>.() -> Unit = {}) {
125+
calls.add(CallBuilder<List<String>>(url).apply(block).build())
126+
}
128127

129128
fun build(): Session = Session(calls, concurrency, delay, rateOptions)
130129
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package net.devslash
22

33
interface SessionManager {
4-
fun call(call: Call, jar: CookieJar)
5-
fun call(call: Call)
4+
fun <T> call(call: Call<T>, jar: CookieJar)
5+
fun <T> call(call: Call<T>)
66
}

api/src/main/kotlin/net/devslash/err/RetryOnTransitiveError.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import net.devslash.HttpRequest
77
import net.devslash.RequestData
88
import java.net.SocketTimeoutException
99

10-
class RetryOnTransitiveError : ChannelReceiving<Pair<HttpRequest, RequestData>> {
11-
override suspend fun accept(channel: Channel<Envelope<Pair<HttpRequest, RequestData>>>,
12-
envelope: Envelope<Pair<HttpRequest, RequestData>>,
10+
class RetryOnTransitiveError<T> : ChannelReceiving<Pair<HttpRequest, RequestData<T>>> {
11+
override suspend fun accept(channel: Channel<Envelope<Pair<HttpRequest, RequestData<T>>>>,
12+
envelope: Envelope<Pair<HttpRequest, RequestData<T>>>,
1313
e: Exception) {
1414
if (!envelope.shouldProceed()) {
1515
// fail after a few failures

benchmarks/src/jmh/kotlin/net/devslash/Bencho.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package net.devslash
22

3-
import net.devslash.data.ListDataSupplier
43
import org.openjdk.jmh.annotations.*
54
import java.util.concurrent.TimeUnit
65

build.gradle.kts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ buildscript {
1717
plugins {
1818
base
1919
`maven-publish`
20-
kotlin("jvm") version "1.3.50" apply false
20+
kotlin("jvm") version "1.4.20" apply false
2121
id("com.jfrog.bintray") version "1.8.4" apply false }
2222

2323
repositories {
@@ -51,13 +51,6 @@ subprojects {
5151
}
5252
}
5353

54-
// tasks.withType(Test::class).configureEach {
55-
// useJUnitPlatform()
56-
// testLogging {
57-
// events("passed", "skipped", "failed")
58-
// }
59-
// }
60-
6154
configure<BintrayExtension> {
6255
user = project.findProperty("bintrayUser") as String? ?: System.getenv("BINTRAY_USER")
6356
key = project.findProperty("bintrayApiKey") as String? ?: System.getenv("BINTRAY_API_KEY")

examples/src/main/kotlin/net/devslash/examples/PipeExample.kt

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
package net.devslash.examples
22

3-
import io.ktor.application.call
4-
import io.ktor.response.respondText
5-
import io.ktor.routing.get
6-
import io.ktor.routing.routing
7-
import io.ktor.server.engine.embeddedServer
8-
import io.ktor.server.netty.Netty
9-
import net.devslash.data.FileDataSupplier
10-
import net.devslash.outputs.WriteFile
3+
import io.ktor.application.*
4+
import io.ktor.response.*
5+
import io.ktor.routing.*
6+
import io.ktor.server.engine.*
7+
import io.ktor.server.netty.*
8+
import net.devslash.data.ListDataSupplier
119
import net.devslash.pipes.ResettablePipe
1210
import net.devslash.runHttp
1311
import java.net.ServerSocket
1412
import java.util.concurrent.TimeUnit
1513

1614
fun main() {
17-
val pipe = ResettablePipe({ r, _ -> listOf(String(r.body)) })
15+
val pipe = ResettablePipe<String> { r, _ -> listOf(String(r.body)) }
1816
val port = ServerSocket(0).use { it.localPort }
1917
val server = embeddedServer(Netty, port) {
2018
routing {
@@ -27,10 +25,11 @@ fun main() {
2725
val address = "http://localhost:$port"
2826
runHttp {
2927
call(address) {
30-
data = FileDataSupplier(this.javaClass.getResource("/in.log").path)
28+
// Ok this asserting that it passesa round List types as its big object. therefore this should
29+
data = ListDataSupplier(listOf("1"))
3130
after {
3231
+pipe
33-
+WriteFile("!1!")
32+
// +WriteFileeFile<Int>("!1!")
3433
}
3534
}
3635
call(address) {

extensions/src/main/kotlin/net/devslash/data/FileDataSupplier.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import net.devslash.RequestDataSupplier
66
import java.io.File
77
import java.util.concurrent.atomic.AtomicInteger
88

9-
class FileDataSupplier(val name: String, private val split: String = " ") : RequestDataSupplier {
9+
class FileDataSupplier(val name: String, private val split: String = " ") : RequestDataSupplier<List<String>> {
1010
private val sourceFile = File(name).readLines()
1111
private val line = AtomicInteger(0)
1212

13-
override suspend fun getDataForRequest(): RequestData? {
13+
override suspend fun getDataForRequest(): RequestData<List<String>>? {
1414
val ourLine = sourceFile.getOrNull(line.getAndIncrement())?.split(split)
1515
return if (ourLine == null) null else ListBasedRequestData(ourLine)
1616
}

0 commit comments

Comments
 (0)