summaryrefslogtreecommitdiff
path: root/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java
diff options
context:
space:
mode:
Diffstat (limited to 'xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java')
-rw-r--r--xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java149
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