Skip to content

Commit

Permalink
fix #1805
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieuancelin committed Jan 2, 2024
1 parent ffbf580 commit 6a48467
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 91 deletions.
39 changes: 37 additions & 2 deletions otoroshi/app/next/plugins/api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -855,13 +855,48 @@ case class BackendCallResponse(response: NgPluginHttpResponse, rawResponse: Opti

trait NgBackendCall extends NgNamedPlugin {
def useDelegates: Boolean
def bodyResponse(
def sourceBodyResponse(
status: Int,
headers: Map[String, String],
body: Source[ByteString, _]
): Either[NgProxyEngineError, BackendCallResponse] = {
val finalHeaders = headers.getIgnoreCase("Transfer-Encoding") match {
case None => headers.getIgnoreCase("Content-Length") match {
case None => headers ++ Map("Transfer-Encoding" -> s"chunked")
case Some(_) => headers ++ Map("Transfer-Encoding" -> s"chunked") - "Content-Length" - "content-length"
}
case Some(_) => headers
}
BackendCallResponse(
NgPluginHttpResponse(status, finalHeaders, Seq.empty, body),
None
).right[NgProxyEngineError]
}
def inMemoryBodyResponse(
status: Int,
headers: Map[String, String],
body: ByteString
): Either[NgProxyEngineError, BackendCallResponse] = {
val finalHeaders = headers.getIgnoreCase("Transfer-Encoding") match {
case None => headers.getIgnoreCase("Content-Length") match {
case None => headers ++ Map("Content-Length" -> s"${body.length}")
case Some(_) => headers
}
case Some(_) => headers
}
BackendCallResponse(
NgPluginHttpResponse(status, finalHeaders, Seq.empty, body.chunks(16 * 1024)),
None
).right[NgProxyEngineError]
}

def emptyBodyResponse(
status: Int,
headers: Map[String, String],
): Either[NgProxyEngineError, BackendCallResponse] = {
val finalHeaders = headers ++ Map("Content-Length" -> s"0")
BackendCallResponse(
NgPluginHttpResponse(status, headers, Seq.empty, body),
NgPluginHttpResponse(status, finalHeaders, Seq.empty, Source.empty),
None
).right[NgProxyEngineError]
}
Expand Down
52 changes: 25 additions & 27 deletions otoroshi/app/next/plugins/eureka.scala
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,14 @@ class EurekaServerSink extends NgBackendCall {
override def steps: Seq[NgStep] = Seq(NgStep.CallBackend)

private def notFoundResponse() = {
bodyResponse(404, Map("Content-Type" -> "application/json"), Source.empty).vfuture
emptyBodyResponse(404, Map("Content-Type" -> "application/json")).vfuture
}

private def successfulResponse(body: Seq[JsValue]) = {
bodyResponse(
inMemoryBodyResponse(
200,
Map("Content-Type" -> "application/xml"),
otoroshi.utils.xml.Xml.toXml(Json.obj("applications" -> body)).toString().byteString.singleSource
otoroshi.utils.xml.Xml.toXml(Json.obj("applications" -> body)).toString().byteString
).vfuture
}

Expand Down Expand Up @@ -208,32 +208,31 @@ class EurekaServerSink extends NgBackendCall {
)
.flatMap { res =>
if (res) {
bodyResponse(204, Map.empty, Source.empty).vfuture
emptyBodyResponse(204, Map.empty).vfuture
} else {
bodyResponse(
inMemoryBodyResponse(
400,
Map("Content-Type" -> "application/json"),
Json
.obj("error" -> "an error happened during registration of new app")
.stringify
.byteString
.singleSource
).vfuture
}
}
case None =>
bodyResponse(
inMemoryBodyResponse(
400,
Map("Content-Type" -> "application/json"),
Json.obj("error" -> "missing instance id").stringify.byteString.singleSource
Json.obj("error" -> "missing instance id").stringify.byteString
).vfuture
}
}
else
bodyResponse(
inMemoryBodyResponse(
400,
Map("Content-Type" -> "application/json"),
Json.obj("error" -> "missing body or invalid body").stringify.byteString.singleSource
Json.obj("error" -> "missing body or invalid body").stringify.byteString
).vfuture
}

Expand All @@ -248,7 +247,7 @@ class EurekaServerSink extends NgBackendCall {
if (instances.isEmpty)
notFoundResponse()
else
bodyResponse(
inMemoryBodyResponse(
200,
Map("Content-Type" -> "application/xml"),
otoroshi.utils.xml.Xml
Expand All @@ -264,7 +263,6 @@ class EurekaServerSink extends NgBackendCall {
)
.toString()
.byteString
.singleSource
).vfuture
}
}
Expand All @@ -278,13 +276,13 @@ class EurekaServerSink extends NgBackendCall {
.get(s"${env.storageRoot}:plugins:eureka-server-$pluginId:apps:$appId:$instanceId")
.flatMap {
case Some(instance) =>
bodyResponse(
inMemoryBodyResponse(
200,
Map("Content-Type" -> "application/xml"),
otoroshi.utils.xml.Xml.toXml(instance.utf8String.parseJson).toString().byteString.singleSource
otoroshi.utils.xml.Xml.toXml(instance.utf8String.parseJson).toString().byteString
).vfuture
case None =>
bodyResponse(404, Map("Content-Type" -> "application/json"), Source.empty).vfuture
emptyBodyResponse(404, Map("Content-Type" -> "application/json")).vfuture
}
}

Expand All @@ -297,12 +295,12 @@ class EurekaServerSink extends NgBackendCall {
.allMatching(s"${env.storageRoot}:plugins:eureka-server-$pluginId:apps:*:$instanceId")
.flatMap { instances =>
if (instances.isEmpty)
bodyResponse(404, Map("Content-Type" -> "application/json"), Source.empty).vfuture
emptyBodyResponse(404, Map("Content-Type" -> "application/json")).vfuture
else
bodyResponse(
inMemoryBodyResponse(
200,
Map("Content-Type" -> "application/xml"),
otoroshi.utils.xml.Xml.toXml(instances.head.utf8String.parseJson).toString().byteString.singleSource
otoroshi.utils.xml.Xml.toXml(instances.head.utf8String.parseJson).toString().byteString
).vfuture
}
}
Expand All @@ -315,10 +313,10 @@ class EurekaServerSink extends NgBackendCall {
env.datastores.rawDataStore
.del(Seq(s"${env.storageRoot}:plugins:eureka-server-$pluginId:apps:$appId:$instanceId"))
.flatMap { _ =>
bodyResponse(
inMemoryBodyResponse(
200,
Map("Content-Type" -> "application/json"),
Json.obj("deleted" -> "done").stringify.byteString.singleSource
Json.obj("deleted" -> "done").stringify.byteString
).vfuture
}
}
Expand All @@ -332,7 +330,7 @@ class EurekaServerSink extends NgBackendCall {
env.datastores.rawDataStore
.get(key)
.flatMap {
case None => bodyResponse(404, Map("Content-Type" -> "application/json"), Source.empty).vfuture
case None => emptyBodyResponse(404, Map("Content-Type" -> "application/json")).vfuture
case Some(v) =>
env.datastores.rawDataStore
.set(
Expand All @@ -351,8 +349,8 @@ class EurekaServerSink extends NgBackendCall {
(evictionTimeout * 1000).seconds.toMillis.some
)
.flatMap {
case true => bodyResponse(200, Map("Content-Type" -> "application/json"), Source.empty).vfuture
case false => bodyResponse(400, Map.empty, Source.empty).vfuture
case true => emptyBodyResponse(200, Map("Content-Type" -> "application/json")).vfuture
case false => emptyBodyResponse(400, Map.empty).vfuture
}
}
}
Expand Down Expand Up @@ -387,7 +385,7 @@ class EurekaServerSink extends NgBackendCall {
)
.flatMap {
case true =>
bodyResponse(200, Map("Content-Type" -> "application/json"), Source.empty).vfuture
emptyBodyResponse(200, Map("Content-Type" -> "application/json")).vfuture
case false =>
notFoundResponse()
}
Expand All @@ -401,10 +399,10 @@ class EurekaServerSink extends NgBackendCall {
mat: Materializer
) = {
if (queryString.isEmpty)
bodyResponse(
inMemoryBodyResponse(
400,
Map("Content-Type" -> "application/json"),
Json.obj("error" -> "missing query string").stringify.byteString.singleSource
Json.obj("error" -> "missing query string").stringify.byteString
).vfuture
else
env.datastores.rawDataStore
Expand Down Expand Up @@ -435,7 +433,7 @@ class EurekaServerSink extends NgBackendCall {
)
.flatMap {
case true =>
bodyResponse(200, Map("Content-Type" -> "application/json"), Source.empty).vfuture
emptyBodyResponse(200, Map("Content-Type" -> "application/json")).vfuture
case false =>
notFoundResponse()
}
Expand Down
24 changes: 12 additions & 12 deletions otoroshi/app/next/plugins/files.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,25 @@ class StaticBackend extends NgBackendCall {
val filePath = fileUtils.normalize(askedFilePath, config.rootPath)
fileCache.getIfPresent(filePath) match {
case Some((contentType, content)) =>
bodyResponse(200, Map("Content-Type" -> contentType), Source(content.grouped(16 * 1024).toList)).vfuture
inMemoryBodyResponse(200, Map("Content-Type" -> contentType), content).vfuture
case None => {
val file = new File(filePath)
if (!file.exists()) {
bodyResponse(
inMemoryBodyResponse(
404,
Map("Content-Type" -> "text/plain"),
Source.single("resource not found".byteString)
"resource not found".byteString
).vfuture
} else {
val content = ByteString(Files.readAllBytes(Path.of(filePath)))
val contentType = fileUtils.contentType(filePath)
fileCache.put(filePath, (contentType, content))
bodyResponse(200, Map("Content-Type" -> contentType), Source(content.grouped(16 * 1024).toList)).vfuture
inMemoryBodyResponse(200, Map("Content-Type" -> contentType), content).vfuture
}
}
}
} else {
bodyResponse(405, Map("Content-Type" -> "text/plain"), Source.single("method not allowed".byteString)).vfuture
inMemoryBodyResponse(405, Map("Content-Type" -> "text/plain"), "method not allowed".byteString).vfuture
}
}
}
Expand Down Expand Up @@ -256,26 +256,26 @@ class S3Backend extends NgBackendCall {
normalizeKey(key, config).map(_.replace("//", "/")).flatMap { filePath =>
fileCache.getIfPresent(cacheKey) match {
case Some((om, content)) =>
bodyResponse(200, buildHeaders(om), Source(content.grouped(16 * 1024).toList)).vfuture
inMemoryBodyResponse(200, buildHeaders(om), content).vfuture
case None => {
fileExists(filePath, config).flatMap {
case false =>
bodyResponse(
inMemoryBodyResponse(
404,
Map("Content-Type" -> "text/plain"),
Source.single("resource not found".byteString)
"resource not found".byteString
).vfuture
case true => {
fileContent(filePath, config).flatMap {
case None =>
bodyResponse(
inMemoryBodyResponse(
404,
Map("Content-Type" -> "text/plain"),
Source.single("resource not found".byteString)
"resource not found".byteString
).vfuture
case Some((om, content)) => {
fileCache.put(cacheKey, (om, content))
bodyResponse(200, buildHeaders(om), Source(content.grouped(16 * 1024).toList)).vfuture
inMemoryBodyResponse(200, buildHeaders(om), content).vfuture
}
}
}
Expand All @@ -284,7 +284,7 @@ class S3Backend extends NgBackendCall {
}
}
} else {
bodyResponse(405, Map("Content-Type" -> "text/plain"), Source.single("method not allowed".byteString)).vfuture
inMemoryBodyResponse(405, Map("Content-Type" -> "text/plain"), "method not allowed".byteString).vfuture
}
}
}
Loading

0 comments on commit 6a48467

Please sign in to comment.