Skip to content
This repository was archived by the owner on Mar 8, 2024. It is now read-only.

Commit 31c4f56

Browse files
committed
Updated wrappers
- created the following classes - 'MessageContext' - 'ClientMessageContext' - deleted the following classes - 'EndpointContext' (moved its functions to 'MessageContext') - 'ExtrasExtension' (moved its functions to 'ExtrasWrapper') - 'MessageExtension' (moved its functions to 'MessageWrapper') - 'RequestExtension' (moved its functions to 'RequestWrapper') - 'ResponseExtension' (moved its functions to 'ResponseWrapper') - updated the following classes to extend 'MessageContext' - 'RequestContext' - 'ResponseContext' - 'ClientMessageContext' - updated the following classes to extend 'ClientMessageContext' - 'ClientRequestContext' - 'ClientResponseContext' - updated the extensions of the following packages - 'org.cufy.http' - 'org.cufy.http.wrapper' - 'org.cufy.http.pipeline.wrapper' - 'org.cufy.http.pipeline' - 'org.cufy.http.client.wrapper' - 'org.cufy.http.body' - 'org.cufy.http.json' - 'org.cufy.http.concurrent.wrapper' - 'org.cufy.http.mime' - 'org.cufy.http.uri' - updated 'OkEngine' to support canceling requests - updated 'ClientEngine' to allow it to throw any throwable - updated the default next functions of 'ClientRequestContextImpl' and 'ClientResponseContextImpl' to do nothing (instead of printing the error if any) - updated 'Http.open(Endpoint, Middleware...)' to use the endpoint provided instead of dynamically getting the endpoint - renamed the class 'TaskContext' to 'StrategyContext' - updated the generics of 'ClientEngine' - updated tests
1 parent d5452d4 commit 31c4f56

37 files changed

Lines changed: 1988 additions & 1887 deletions

src/main/java/org/cufy/http/body/SerializableBody.kt

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,40 @@ import kotlinx.serialization.json.Json
2323
import kotlinx.serialization.json.decodeFromStream
2424
import kotlinx.serialization.serializer
2525
import org.cufy.http.Body
26-
import org.cufy.http.Message
2726
import org.cufy.http.mime.Mime
2827
import org.cufy.http.mime.MimeSubtype
2928
import org.cufy.http.mime.MimeType
30-
import org.cufy.http.wrapper.MessageExtension
31-
import org.cufy.http.wrapper.body
3229
import java.io.InputStream
3330
import java.nio.charset.StandardCharsets
31+
import java.util.*
3432

33+
/**
34+
* A body implementation that holds a serializable value of type [T].
35+
*
36+
* @author LSafer
37+
* @version 1.0.0
38+
* @since 1.0.0 ~2022.01.08
39+
*/
3540
open class SerializableBody<T>(
41+
/**
42+
* The serialized value.
43+
*/
3644
var value: T,
45+
/**
46+
* The mime of the body.
47+
*/
48+
mime: Mime? = Mime(MimeType.APPLICATION, MimeSubtype.JSON),
49+
/**
50+
* The serializer to be used to serialize the value.
51+
*/
3752
private val serializer: KSerializer<T>,
53+
/**
54+
* The format to be used to serialize the value.
55+
*/
3856
private val format: Json = Json
3957
) : Body() {
4058
init {
41-
mime = Mime(MimeType.APPLICATION, MimeSubtype.JSON)
59+
this.mime = mime
4260
}
4361

4462
companion object {
@@ -50,8 +68,8 @@ open class SerializableBody<T>(
5068
format: Json = Json
5169
) = SerializableBody(
5270
format.decodeFromStream<T>(body.openInputStream()),
53-
format.serializersModule.serializer(),
54-
format
71+
serializer = format.serializersModule.serializer(),
72+
format = format
5573
)
5674

5775
inline fun <reified T> parse(
@@ -60,43 +78,28 @@ open class SerializableBody<T>(
6078
format: Json = Json
6179
) = SerializableBody(
6280
format.decodeFromString<T>(source),
63-
format.serializersModule.serializer(),
64-
format
81+
serializer = format.serializersModule.serializer(),
82+
format = format
6583
)
6684
}
6785

6886
override fun openInputStream(): InputStream =
69-
format.encodeToString(serializer, value)
87+
this.format.encodeToString(this.serializer, this.value)
7088
.byteInputStream(StandardCharsets.UTF_8)
7189

7290
override fun toString(): String =
73-
format.encodeToString(serializer, value)
91+
this.format.encodeToString(this.serializer, this.value)
7492

7593
override fun hashCode(): Int =
76-
value.hashCode()
94+
Objects.hash(this.value.hashCode())
7795

7896
override fun equals(other: Any?): Boolean =
79-
other is SerializableBody<*> && other.value == this.value
97+
other is SerializableBody<*> && Objects.equals(this.value, other.value)
8098

81-
override fun clone(): Body =
82-
SerializableBody(value, serializer, format)
99+
override fun clone(): Body {
100+
@Suppress("UNCHECKED_CAST")
101+
val clone: SerializableBody<T> = super.clone() as SerializableBody<T>
102+
clone.mime = this.mime?.clone()
103+
return clone
104+
}
83105
}
84-
85-
inline fun <reified T> SerializableBody(
86-
value: T,
87-
format: Json = Json
88-
) = SerializableBody(
89-
value,
90-
format.serializersModule.serializer(),
91-
format
92-
)
93-
94-
/** Assuming the body is [SerializableBody], this method is a shortcut for [SerializableBody.value] */
95-
@Suppress("UNCHECKED_CAST")
96-
fun <M : Message, T : MessageExtension<M, *>, S> T.serializable(): S =
97-
(body as SerializableBody<S>).value
98-
99-
/** Assuming the body is [SerializableBody], this method is a shortcut for [SerializableBody.value] */
100-
@Suppress("UNCHECKED_CAST")
101-
fun <M : Message, T : MessageExtension<M, *>, S> T.serializable(serializable: S): T =
102-
apply { (body as SerializableBody<S>).value = serializable }

src/main/java/org/cufy/http/body/extensions.kt

Lines changed: 94 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,53 @@
1515
*/
1616
package org.cufy.http.body
1717

18+
import kotlinx.serialization.json.Json
19+
import kotlinx.serialization.serializer
1820
import org.cufy.http.Message
19-
import org.cufy.http.wrapper.MessageExtension
20-
import org.cufy.http.wrapper.body
2121
import org.cufy.http.json.JsonElement
22+
import org.cufy.http.mime.Mime
23+
import org.cufy.http.wrapper.MessageWrapper
24+
import org.cufy.http.wrapper.body
2225
import java.io.File
2326

27+
// ParametersBody
28+
2429
/** An alias for [ParametersBody.put] and [ParametersBody.remove]. */
2530
@JvmName("putAt")
2631
operator fun ParametersBody.set(name: String, value: String?): Unit =
2732
if (value === null) remove(name) else put(name, value)
2833

34+
/** Assuming the body is [ParametersBody], this method is a shortcut for [ParametersBody.get] */
35+
fun <M : Message, Self : MessageWrapper<M, *>> Self.parameter(name: String): String? =
36+
(body as ParametersBody)[name]
37+
38+
/** Assuming the body is [ParametersBody], this method is a shortcut for [ParametersBody.put] */
39+
fun <M : Message, Self : MessageWrapper<M, *>> Self.parameter(
40+
name: String,
41+
value: String
42+
) =
43+
apply { (body as ParametersBody)[name] = value }
44+
45+
// JsonBody
46+
2947
/** An alias for [JsonBody.put] and [JsonBody.remove] */
3048
@JvmName("putAt")
3149
operator fun JsonBody.set(path: String, element: JsonElement?): Unit =
3250
if (element === null) remove(path) else put(path, element)
3351

52+
/** Assuming the body is [JsonBody], this method is a shortcut for [JsonBody.get] */
53+
fun <M : Message, Self : MessageWrapper<M, *>> Self.json(path: String): JsonElement? =
54+
(body as JsonBody)[path]
55+
56+
/** Assuming the body is [JsonBody], this method is a shortcut for [JsonBody.put] */
57+
fun <M : Message, Self : MessageWrapper<M, *>> Self.json(
58+
path: String,
59+
element: JsonElement?
60+
) =
61+
apply { (body as JsonBody)[path] = element }
62+
63+
// MultipartBody
64+
3465
/** An alias for [MultipartBody.put] and [MultipartBody.remove]. */
3566
@JvmName("putAt")
3667
operator fun MultipartBody.set(index: Int, part: BodyPart?): Unit =
@@ -41,59 +72,82 @@ operator fun MultipartBody.set(index: Int, part: BodyPart?): Unit =
4172
operator fun MultipartBody.plusAssign(part: BodyPart): Unit =
4273
add(part)
4374

44-
/** An alias for [TextBody.append]. */
45-
@JvmName("leftShift")
46-
operator fun TextBody.plusAssign(content: Any?): Unit =
47-
append(content)
48-
49-
/** Assuming the body is [ParametersBody], this method is a shortcut for [ParametersBody.put] */
50-
fun <M : Message, T : MessageExtension<M, *>> T.parameter(name: String, value: String) =
51-
apply { (body as ParametersBody)[name] = value }
52-
53-
/** Assuming the body is [JsonBody], this method is a shortcut for [JsonBody.put] */
54-
fun <M : Message, T : MessageExtension<M, *>> T.json(path: String, element: JsonElement?) =
55-
apply { (body as JsonBody)[path] = element }
75+
/** Assuming the body is [MultipartBody], this method is a shortcut for [MultipartBody.get] */
76+
fun <M : Message, Self : MessageWrapper<M, *>> Self.part(index: Int): BodyPart? =
77+
(body as MultipartBody)[index]
5678

5779
/** Assuming the body is [MultipartBody], this method is a shortcut for [MultipartBody.add] */
58-
fun <M : Message, T : MessageExtension<M, *>> T.part(part: BodyPart): T =
80+
fun <M : Message, Self : MessageWrapper<M, *>> Self.part(part: BodyPart): Self =
5981
apply { (body as MultipartBody) += part }
6082

6183
/** Assuming the body is [MultipartBody], this method is a shortcut for [MultipartBody.put] */
62-
fun <M : Message, T : MessageExtension<M, *>> T.part(index: Int, part: BodyPart): T =
84+
fun <M : Message, Self : MessageWrapper<M, *>> Self.part(
85+
index: Int,
86+
part: BodyPart
87+
): Self =
6388
apply { (body as MultipartBody)[index] = part }
6489

65-
/** Assuming the body is [TextBody], this method is a shortcut for [TextBody.append] */
66-
fun <M : Message, T : MessageExtension<M, *>> T.append(vararg content: Any?): T =
67-
apply { (body as TextBody) += content }
68-
69-
/** Assuming the body is [FileBody], this method is a shortcut for [FileBody.setFile] */
70-
fun <M : Message, T : MessageExtension<M, *>> T.file(file: File): T =
71-
apply { (body as FileBody).file = file }
90+
// TextBody
7291

73-
/** Assuming the body is [BytesBody], this method is a shortcut for [BytesBody.setBytes] */
74-
fun <M : Message, T : MessageExtension<M, *>> T.bytes(bytes: ByteArray): T =
75-
apply { (body as BytesBody).bytes = bytes }
92+
/** An alias for [TextBody.append]. */
93+
@JvmName("leftShift")
94+
operator fun TextBody.plusAssign(content: Any?): Unit =
95+
append(content)
7696

77-
/** Assuming the body is [ParametersBody], this method is a shortcut for [ParametersBody.get] */
78-
fun <M : Message, T : MessageExtension<M, *>> T.parameter(name: String): String? =
79-
(body as ParametersBody)[name]
97+
/** Assuming the body is [TextBody], this method is a shortcut for [TextBody.toString] */
98+
fun <M : Message, Self : MessageWrapper<M, *>> Self.text(): String =
99+
(body as TextBody).toString()
80100

81-
/** Assuming the body is [JsonBody], this method is a shortcut for [JsonBody.get] */
82-
fun <M : Message, T : MessageExtension<M, *>> T.json(path: String): JsonElement? =
83-
(body as JsonBody)[path]
101+
/** Assuming the body is [TextBody], this method is a shortcut for [TextBody.append] */
102+
fun <M : Message, Self : MessageWrapper<M, *>> Self.append(vararg content: Any?): Self =
103+
apply { (body as TextBody) += content }
84104

85-
/** Assuming the body is [MultipartBody], this method is a shortcut for [MultipartBody.get] */
86-
fun <M : Message, T : MessageExtension<M, *>> T.part(index: Int): BodyPart? =
87-
(body as MultipartBody)[index]
105+
// FileBody
88106

89107
/** Assuming the body is [FileBody], this method is a shortcut for [FileBody.getFile] */
90-
fun <M : Message, T : MessageExtension<M, *>> T.file(): File =
108+
fun <M : Message, Self : MessageWrapper<M, *>> Self.file(): File =
91109
(body as FileBody).file
92110

111+
/** Assuming the body is [FileBody], this method is a shortcut for [FileBody.setFile] */
112+
fun <M : Message, Self : MessageWrapper<M, *>> Self.file(file: File): Self =
113+
apply { (body as FileBody).file = file }
114+
115+
// BytesBody
116+
93117
/** Assuming the body is [BytesBody], this method is a shortcut for [BytesBody.getBytes] */
94-
fun <M : Message, T : MessageExtension<M, *>> T.bytes(): ByteArray =
118+
fun <M : Message, Self : MessageWrapper<M, *>> Self.bytes(): ByteArray =
95119
(body as BytesBody).bytes
96120

97-
/** Assuming the body is [TextBody], this method is a shortcut for [TextBody.toString] */
98-
fun <M : Message, T : MessageExtension<M, *>> T.text(): String =
99-
(body as TextBody).toString()
121+
/** Assuming the body is [BytesBody], this method is a shortcut for [BytesBody.setBytes] */
122+
fun <M : Message, Self : MessageWrapper<M, *>> Self.bytes(bytes: ByteArray): Self =
123+
apply { (body as BytesBody).bytes = bytes }
124+
125+
// SerializableBody
126+
127+
/**
128+
* Construct a new serializable body for the given [value].
129+
*
130+
* @param value the initial value for the constructed body.
131+
* @param format the json format to be used when serializing [value].
132+
* @since 1.0.0 ~2022.01.08
133+
*/
134+
inline fun <reified T> SerializableBody(
135+
value: T,
136+
mime: Mime?,
137+
format: Json = Json
138+
) = SerializableBody(
139+
value,
140+
mime,
141+
format.serializersModule.serializer(),
142+
format
143+
)
144+
145+
/** Assuming the body is [SerializableBody], this method is a shortcut for [SerializableBody.value] */
146+
@Suppress("UNCHECKED_CAST")
147+
fun <T, M : Message, Self : MessageWrapper<M, *>> Self.serializable(): T =
148+
(body as SerializableBody<T>).value
149+
150+
/** Assuming the body is [SerializableBody], this method is a shortcut for [SerializableBody.value] */
151+
@Suppress("UNCHECKED_CAST")
152+
fun <T, M : Message, Self : MessageWrapper<M, *>> Self.serializable(serializable: T): Self =
153+
apply { (body as SerializableBody<T>).value = serializable }

src/main/java/org/cufy/http/client/ClientEngine.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,11 @@ public void invoke(@Nullable Throwable error) {
7575

7676
ClientEngine<I, O> engine = iterator.next();
7777

78-
engine.connect(input, this);
78+
try {
79+
engine.connect(input, this);
80+
} catch (Throwable e) {
81+
next.invoke(e);
82+
}
7983
}
8084
}.invoke();
8185
};
@@ -91,7 +95,8 @@ public void invoke(@Nullable Throwable error) {
9195
* null.
9296
* @throws UnsupportedOperationException if this engine does not support this
9397
* function.
98+
* @throws Throwable if any exception occurs while connecting.
9499
* @since 0.3.0 ~2021.12.23
95100
*/
96-
void connect(@NotNull I input, @NotNull Next<O> next);
101+
void connect(@NotNull I input, @NotNull Next<O> next) throws Throwable;
97102
}

src/main/java/org/cufy/http/client/Http.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public static ClientResponseContext<Endpoint> fetch(
8787
@NotNull
8888
@Contract("_,_->new")
8989
public static ClientResponseContext<Endpoint> fetch(
90-
@NotNull ClientEngine<ClientRequestContext<?>, ClientResponseContext<?>> engine,
90+
@NotNull ClientEngine<ClientRequestContext<? extends Endpoint>, ClientResponseContext<? extends Endpoint>> engine,
9191
@Nullable Middleware<? super ClientRequestContext<Endpoint>> @NotNull ... middlewares
9292
) {
9393
return Http.open(middlewares)
@@ -139,7 +139,7 @@ public static <E extends Endpoint> ClientResponseContext<E> fetch(
139139
@NotNull
140140
@Contract("_,_,_->new")
141141
public static <E extends Endpoint> ClientResponseContext<E> fetch(
142-
@NotNull ClientEngine<ClientRequestContext<?>, ClientResponseContext<?>> engine,
142+
@NotNull ClientEngine<ClientRequestContext<? extends Endpoint>, ClientResponseContext<? extends Endpoint>> engine,
143143
@NotNull E endpoint,
144144
@Nullable Middleware<? super ClientRequestContext<E>> @NotNull ... middlewares
145145
) {
@@ -192,7 +192,7 @@ public static ClientResponseContext<Endpoint> fetch(
192192
@NotNull
193193
@Contract("_,_,_,_->new")
194194
public static ClientResponseContext<Endpoint> fetch(
195-
@NotNull ClientEngine<ClientRequestContext<?>, ClientResponseContext<?>> engine,
195+
@NotNull ClientEngine<ClientRequestContext<? extends Endpoint>, ClientResponseContext<? extends Endpoint>> engine,
196196
@NotNull @Pattern(HttpRegExp.METHOD) String method,
197197
@NotNull @Pattern(UriRegExp.URI_REFERENCE) String uri,
198198
@Nullable Middleware<? super ClientRequestContext<Endpoint>> @NotNull ... middlewares
@@ -244,7 +244,7 @@ public static ClientResponseContext<Endpoint> fetch(
244244
@NotNull
245245
@Contract("_,_,_->new")
246246
public static ClientResponseContext<Endpoint> fetch(
247-
@NotNull ClientEngine<ClientRequestContext<?>, ClientResponseContext<?>> engine,
247+
@NotNull ClientEngine<ClientRequestContext<? extends Endpoint>, ClientResponseContext<? extends Endpoint>> engine,
248248
@NotNull Strategy strategy,
249249
@Nullable Middleware<? super ClientRequestContext<Endpoint>> @NotNull ... middlewares
250250
) {
@@ -302,7 +302,7 @@ public static <E extends Endpoint> ClientResponseContext<E> fetch(
302302
@NotNull
303303
@Contract("_,_,_,_->new")
304304
public static <E extends Endpoint> ClientResponseContext<E> fetch(
305-
@NotNull ClientEngine<ClientRequestContext<?>, ClientResponseContext<?>> engine,
305+
@NotNull ClientEngine<ClientRequestContext<? extends Endpoint>, ClientResponseContext<? extends Endpoint>> engine,
306306
@NotNull Strategy strategy,
307307
@NotNull E endpoint,
308308
@Nullable Middleware<? super ClientRequestContext<E>> @NotNull ... middlewares
@@ -363,7 +363,7 @@ public static ClientResponseContext<Endpoint> fetch(
363363
@NotNull
364364
@Contract("_,_,_,_,_->new")
365365
public static ClientResponseContext<Endpoint> fetch(
366-
@NotNull ClientEngine<ClientRequestContext<?>, ClientResponseContext<?>> engine,
366+
@NotNull ClientEngine<ClientRequestContext<? extends Endpoint>, ClientResponseContext<? extends Endpoint>> engine,
367367
@NotNull Strategy strategy,
368368
@NotNull @Pattern(HttpRegExp.METHOD) String method,
369369
@NotNull @Pattern(UriRegExp.URI_REFERENCE) String uri,
@@ -422,7 +422,7 @@ public static <E extends Endpoint> ClientRequestContext<E> open(
422422
Objects.requireNonNull(middlewares, "middlewares");
423423
ClientRequestContext<E> req = new ClientRequestContextImpl<>(endpoint);
424424
endpoint.prepare(req.request());
425-
req.interceptor(res -> res.endpoint().accept(res.response()));
425+
req.interceptor(res -> endpoint.accept(res.response()));
426426
req.inject(Middleware.combine(middlewares));
427427
return req;
428428
}

0 commit comments

Comments
 (0)