diff options
Diffstat (limited to 'xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java')
-rw-r--r-- | xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java new file mode 100644 index 000000000000..e92d20eebffc --- /dev/null +++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java @@ -0,0 +1,149 @@ +package org.jetbrains.io.fastCgi; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.util.CharsetUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.builtInWebServer.PathInfo; +import org.jetbrains.builtInWebServer.WebServerPathToFileManager; +import org.jetbrains.io.Responses; + +import java.net.InetSocketAddress; +import java.util.Locale; +import java.util.Map; + +public class FastCgiRequest { + private static final int PARAMS = 4; + private static final int BEGIN_REQUEST = 1; + private static final int RESPONDER = 1; + private static final int FCGI_KEEP_CONNECTION = 1; + private static final int STDIN = 5; + private static final int VERSION = 1; + + private final ByteBuf buffer; + final int requestId; + + public FastCgiRequest(int requestId, @NotNull ByteBufAllocator allocator) { + this.requestId = requestId; + + buffer = allocator.buffer(); + writeHeader(buffer, BEGIN_REQUEST, FastCgiConstants.HEADER_LENGTH); + buffer.writeShort(RESPONDER); + buffer.writeByte(FCGI_KEEP_CONNECTION); + buffer.writeZero(5); + } + + public void writeFileHeaders(@NotNull VirtualFile file, @NotNull Project project, @NotNull CharSequence canonicalRequestPath) { + PathInfo root = WebServerPathToFileManager.getInstance(project).getRoot(file); + FastCgiService.LOG.assertTrue(root != null); + addHeader("DOCUMENT_ROOT", root.getRoot().getPath()); + addHeader("SCRIPT_FILENAME", file.getPath()); + addHeader("SCRIPT_NAME", canonicalRequestPath); + } + + public final void addHeader(@NotNull String key, @Nullable CharSequence value) { + if (value == null) { + return; + } + + int keyLength = key.length(); + int valLength = value.length(); + writeHeader(buffer, PARAMS, keyLength + valLength + (keyLength < 0x80 ? 1 : 4) + (valLength < 0x80 ? 1 : 4)); + + if (keyLength < 0x80) { + buffer.writeByte(keyLength); + } + else { + buffer.writeByte(0x80 | (keyLength >> 24)); + buffer.writeByte(keyLength >> 16); + buffer.writeByte(keyLength >> 8); + buffer.writeByte(keyLength); + } + + if (valLength < 0x80) { + buffer.writeByte(valLength); + } + else { + buffer.writeByte(0x80 | (valLength >> 24)); + buffer.writeByte(valLength >> 16); + buffer.writeByte(valLength >> 8); + buffer.writeByte(valLength); + } + + buffer.writeBytes(key.getBytes(CharsetUtil.US_ASCII)); + buffer.writeBytes(Unpooled.copiedBuffer(value, CharsetUtil.UTF_8)); + } + + public void writeHeaders(FullHttpRequest request, Channel clientChannel) { + addHeader("REQUEST_URI", request.uri()); + addHeader("REQUEST_METHOD", request.method().name()); + + InetSocketAddress remote = (InetSocketAddress)clientChannel.remoteAddress(); + addHeader("REMOTE_ADDR", remote.getAddress().getHostAddress()); + addHeader("REMOTE_PORT", Integer.toString(remote.getPort())); + + InetSocketAddress local = (InetSocketAddress)clientChannel.localAddress(); + addHeader("SERVER_SOFTWARE", Responses.getServerHeaderValue()); + addHeader("SERVER_NAME", Responses.getServerHeaderValue()); + + addHeader("SERVER_ADDR", local.getAddress().getHostAddress()); + addHeader("SERVER_PORT", Integer.toString(local.getPort())); + + addHeader("GATEWAY_INTERFACE", "CGI/1.1"); + addHeader("SERVER_PROTOCOL", request.protocolVersion().text()); + addHeader("CONTENT_TYPE", request.headers().get(HttpHeaders.Names.CONTENT_TYPE)); + + // PHP only, required if PHP was built with --enable-force-cgi-redirect + addHeader("REDIRECT_STATUS", "200"); + + String queryString = ""; + int queryIndex = request.uri().indexOf('?'); + if (queryIndex != -1) { + queryString = request.uri().substring(queryIndex + 1); + } + addHeader("QUERY_STRING", queryString); + + addHeader("CONTENT_LENGTH", String.valueOf(request.content().readableBytes())); + + for (Map.Entry<String, String> entry : request.headers()) { + addHeader("HTTP_" + entry.getKey().replace('-', '_').toUpperCase(Locale.ENGLISH), entry.getValue()); + } + } + + final void writeToServerChannel(ByteBuf content, Channel fastCgiChannel) { + writeHeader(buffer, PARAMS, 0); + fastCgiChannel.write(buffer); + + if (content.isReadable()) { + ByteBuf headerBuffer = fastCgiChannel.alloc().buffer(FastCgiConstants.HEADER_LENGTH, FastCgiConstants.HEADER_LENGTH); + writeHeader(headerBuffer, STDIN, content.readableBytes()); + fastCgiChannel.write(headerBuffer); + + fastCgiChannel.write(content); + + headerBuffer = fastCgiChannel.alloc().buffer(FastCgiConstants.HEADER_LENGTH, FastCgiConstants.HEADER_LENGTH); + writeHeader(headerBuffer, STDIN, 0); + fastCgiChannel.write(headerBuffer); + } + else { + content.release(); + } + + fastCgiChannel.flush(); + } + + private void writeHeader(ByteBuf buffer, int type, int length) { + buffer.writeByte(VERSION); + buffer.writeByte(type); + buffer.writeShort(requestId); + buffer.writeShort(length); + buffer.writeZero(2); + } +}
\ No newline at end of file |