| // |
| // ======================================================================== |
| // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.fcgi.generator; |
| |
| import java.nio.ByteBuffer; |
| import java.nio.charset.Charset; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.jetty.fcgi.FCGI; |
| import org.eclipse.jetty.http.HttpField; |
| import org.eclipse.jetty.http.HttpFields; |
| import org.eclipse.jetty.http.HttpStatus; |
| import org.eclipse.jetty.io.ByteBufferPool; |
| import org.eclipse.jetty.util.BufferUtil; |
| import org.eclipse.jetty.util.Callback; |
| |
| public class ServerGenerator extends Generator |
| { |
| private static final byte[] STATUS = new byte[]{'S', 't', 'a', 't', 'u', 's'}; |
| private static final byte[] COLON = new byte[]{':', ' '}; |
| private static final byte[] EOL = new byte[]{'\r', '\n'}; |
| |
| private final boolean sendStatus200; |
| |
| public ServerGenerator(ByteBufferPool byteBufferPool) |
| { |
| this(byteBufferPool, true); |
| } |
| |
| public ServerGenerator(ByteBufferPool byteBufferPool, boolean sendStatus200) |
| { |
| super(byteBufferPool); |
| this.sendStatus200 = sendStatus200; |
| } |
| |
| public Result generateResponseHeaders(int request, int code, String reason, HttpFields fields, Callback callback) |
| { |
| request &= 0xFF_FF; |
| |
| Charset utf8 = Charset.forName("UTF-8"); |
| List<byte[]> bytes = new ArrayList<>(fields.size() * 2); |
| int length = 0; |
| |
| if (code != 200 || sendStatus200) |
| { |
| // Special 'Status' header |
| bytes.add(STATUS); |
| length += STATUS.length + COLON.length; |
| if (reason == null) |
| reason = HttpStatus.getMessage(code); |
| byte[] responseBytes = (code + " " + reason).getBytes(utf8); |
| bytes.add(responseBytes); |
| length += responseBytes.length + EOL.length; |
| } |
| |
| // Other headers |
| for (HttpField field : fields) |
| { |
| String name = field.getName(); |
| byte[] nameBytes = name.getBytes(utf8); |
| bytes.add(nameBytes); |
| |
| String value = field.getValue(); |
| byte[] valueBytes = value.getBytes(utf8); |
| bytes.add(valueBytes); |
| |
| length += nameBytes.length + COLON.length; |
| length += valueBytes.length + EOL.length; |
| } |
| // End of headers |
| length += EOL.length; |
| |
| final ByteBuffer buffer = byteBufferPool.acquire(length, true); |
| BufferUtil.clearToFill(buffer); |
| |
| for (int i = 0; i < bytes.size(); i += 2) |
| buffer.put(bytes.get(i)).put(COLON).put(bytes.get(i + 1)).put(EOL); |
| buffer.put(EOL); |
| |
| buffer.flip(); |
| |
| return generateContent(request, buffer, true, false, callback, FCGI.FrameType.STDOUT); |
| } |
| |
| public Result generateResponseContent(int request, ByteBuffer content, boolean lastContent, boolean aborted, Callback callback) |
| { |
| if (aborted) |
| { |
| Result result = new Result(byteBufferPool, callback); |
| if (lastContent) |
| result.append(generateEndRequest(request, true), true); |
| else |
| result.append(BufferUtil.EMPTY_BUFFER, false); |
| return result; |
| } |
| else |
| { |
| Result result = generateContent(request, content, false, lastContent, callback, FCGI.FrameType.STDOUT); |
| if (lastContent) |
| result.append(generateEndRequest(request, false), true); |
| return result; |
| } |
| } |
| |
| private ByteBuffer generateEndRequest(int request, boolean aborted) |
| { |
| request &= 0xFF_FF; |
| ByteBuffer endRequestBuffer = byteBufferPool.acquire(8, false); |
| BufferUtil.clearToFill(endRequestBuffer); |
| endRequestBuffer.putInt(0x01_03_00_00 + request); |
| endRequestBuffer.putInt(0x00_08_00_00); |
| endRequestBuffer.putInt(aborted ? 1 : 0); |
| endRequestBuffer.putInt(0); |
| endRequestBuffer.flip(); |
| return endRequestBuffer; |
| } |
| } |