return false
}
-internal fun validateToken(request: HttpRequest, channel: Channel, redirectToSetCookie: Boolean): HttpHeaders? {
+internal fun validateToken(request: HttpRequest, channel: Channel): HttpHeaders? {
val cookieString = request.headers().get(HttpHeaderNames.COOKIE)
if (cookieString != null) {
val cookies = ServerCookieDecoder.STRICT.decode(cookieString)
val url = "${channel.uriScheme}://${request.host!!}${urlDecoder.path()}"
if (token != null && tokens.getIfPresent(token) != null) {
tokens.invalidate(token)
- if (redirectToSetCookie) {
- // we redirect because it is not easy to change and maintain all places where we send response
- val response = HttpResponseStatus.MOVED_PERMANENTLY.response(request)
- response.headers().add(HttpHeaderNames.LOCATION, url)
- response.headers().set(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(STANDARD_COOKIE) + "; SameSite=strict")
- response.send(channel, request)
- return response.headers()
- }
- else {
- return DefaultHttpHeaders().set(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(STANDARD_COOKIE) + "; SameSite=strict")
- }
+ return DefaultHttpHeaders().set(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(STANDARD_COOKIE) + "; SameSite=strict")
}
SwingUtilities.invokeAndWait {
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.util.Consumer
-import com.intellij.util.containers.ConcurrentIntObjectMap
import com.intellij.util.containers.ContainerUtil
import io.netty.bootstrap.Bootstrap
import io.netty.buffer.ByteBuf
// todo send FCGI_ABORT_REQUEST if client channel disconnected
abstract class FastCgiService(project: Project) : SingleConnectionNetService(project) {
private val requestIdCounter = AtomicInteger()
- protected val requests: ConcurrentIntObjectMap<Channel> = ContainerUtil.createConcurrentIntObjectMap<Channel>()
+ private val requests = ContainerUtil.createConcurrentIntObjectMap<ClientInfo>()
override fun configureBootstrap(bootstrap: Bootstrap, errorOutputConsumer: Consumer<String>) {
bootstrap.handler {
if (!requests.isEmpty) {
val waitingClients = requests.elements().toList()
requests.clear()
- for (channel in waitingClients) {
- sendBadGateway(channel)
+ for (client in waitingClients) {
+ sendBadGateway(client.channel, client.extraHeaders)
}
}
}
}
}
finally {
- val channel = requests.remove(fastCgiRequest.requestId)
- if (channel != null) {
- sendBadGateway(channel)
+ requests.remove(fastCgiRequest.requestId)?.let {
+ sendBadGateway(it.channel, it.extraHeaders)
}
}
}
- fun allocateRequestId(channel: Channel): Int {
+ fun allocateRequestId(channel: Channel, extraHeaders: HttpHeaders): Int {
var requestId = requestIdCounter.getAndIncrement()
if (requestId >= java.lang.Short.MAX_VALUE) {
requestIdCounter.set(0)
requestId = requestIdCounter.getAndDecrement()
}
- requests.put(requestId, channel)
+ requests.put(requestId, ClientInfo(channel, extraHeaders))
return requestId
}
fun responseReceived(id: Int, buffer: ByteBuf?) {
- val channel = requests.remove(id)
- if (channel == null || !channel.isActive) {
+ val client = requests.remove(id)
+ if (client == null || !client.channel.isActive) {
buffer?.release()
return
}
+ val channel = client.channel
if (buffer == null) {
HttpResponseStatus.BAD_GATEWAY.send(channel)
return
if (!HttpUtil.isContentLengthSet(httpResponse)) {
HttpUtil.setContentLength(httpResponse, buffer.readableBytes().toLong())
}
+ httpResponse.headers().add(client.extraHeaders)
}
catch (e: Throwable) {
buffer.release()
}
}
-private fun sendBadGateway(channel: Channel) {
+private fun sendBadGateway(channel: Channel, extraHeaders: HttpHeaders) {
try {
if (channel.isActive) {
- HttpResponseStatus.BAD_GATEWAY.send(channel)
+ HttpResponseStatus.BAD_GATEWAY.send(channel, extraHeaders = extraHeaders)
}
}
catch (e: Throwable) {
response.headers().add(key, value)
}
}
-}
\ No newline at end of file
+}
+
+private class ClientInfo(val channel: Channel, val extraHeaders: HttpHeaders)
\ No newline at end of file