All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.firenio.baseio.codec.http11.ClientHttpCodec Maven / Gradle / Ivy

There is a newer version: 3.2.9.beta11
Show newest version
/*
 * Copyright 2015 The Baseio Project
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.firenio.baseio.codec.http11;

import static com.firenio.baseio.codec.http11.HttpHeader.Content_Length;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.firenio.baseio.buffer.ByteBuf;
import com.firenio.baseio.collection.IntMap;
import com.firenio.baseio.common.Util;
import com.firenio.baseio.component.Channel;
import com.firenio.baseio.component.FastThreadLocal;
import com.firenio.baseio.component.Frame;

/**
 * @author wangkai
 *
 */
public class ClientHttpCodec extends HttpCodec {

    private static final byte[] COOKIE   = b("Cookie:");
    private static final byte[] PROTOCOL = b(" HTTP/1.1\r\nContent-Length: ");

    @Override
    ClientHttpFrame allocHttpFrame(Channel ch) {
        ClientHttpFrame f = (ClientHttpFrame) ch.getAttribute(FRAME_DECODE_KEY);
        if (f == null) {
            return new ClientHttpFrame();
        }
        return f;
    }

    @Override
    int decodeRemainBody(Channel ch, ByteBuf src, HttpFrame frame) {
        ClientHttpFrame f = (ClientHttpFrame) frame;
        if (f.isChunked()) {
            //TODO chunked support
            return decode_state_complate;
        } else {
            if (f.getContent() == null) {
                f.setContent(new byte[f.getContentLength()]);
                f.bodyBuf = ByteBuf.wrap(f.getArrayContent());
            }
            f.bodyBuf.put(src, f.bodyBuf.remaining());
            if (f.bodyBuf.hasRemaining()) {
                return decode_state_body;
            }
            return decode_state_complate;
        }
    }

    @Override
    public ByteBuf encode(Channel ch, Frame frame) throws IOException {
        ClientHttpFrame f = (ClientHttpFrame) frame;
        Object content = f.getContent();
        ByteBuf contentBuf = null;
        byte[] contentArray = null;
        boolean isArray = false;
        int write_size = 0;
        if (content instanceof ByteBuf) {
            contentBuf = ((ByteBuf) content).flip();
            write_size = contentBuf.limit();
        } else if (content instanceof byte[]) {
            isArray = true;
            contentArray = (byte[]) content;
            write_size = contentArray.length;
        }
        byte[] byte32 = FastThreadLocal.get().getBytes32();
        byte[] url_bytes = getRequestURI(f).getBytes();
        byte[] method_bytes = f.getMethod().getBytes();
        int len_idx = Util.valueOf(write_size, byte32);
        int len_len = 32 - len_idx;
        int len = method_bytes.length + 1 + url_bytes.length + PROTOCOL.length + len_len + 2;
        int header_size = 0;
        int cookie_size = 0;
        List encode_bytes_array = getEncodeBytesArray();
        IntMap headers = f.getRequestHeaders();
        if (headers != null) {
            headers.remove(HttpHeader.Content_Length.getId());
            for (headers.scan();headers.hasNext();) {
                byte[] k = HttpHeader.get(headers.nextKey()).getBytes();
                byte[] v = headers.value().getBytes();
                if (v == null) {
                    continue;
                }
                header_size++;
                encode_bytes_array.add(k);
                encode_bytes_array.add(v);
                len += 4;
                len += k.length;
                len += v.length;
            }
        }
        List cookieList = f.getCookieList();
        if (cookieList != null && !cookieList.isEmpty()) {
            len += COOKIE.length;
            for (Cookie c : cookieList) {
                byte[] k = c.getName().getBytes();
                byte[] v = c.getValue().getBytes();
                cookie_size++;
                encode_bytes_array.add(k);
                encode_bytes_array.add(v);
                len += 2;
                len += k.length;
                len += v.length;
            }
        }
        len += 2;
        if (isArray) {
            len += write_size;
        }
        ByteBuf buf = ch.alloc().allocate(len);
        buf.put(method_bytes);
        buf.putByte(SPACE);
        buf.put(url_bytes);
        buf.put(PROTOCOL);
        buf.put(byte32, len_idx, len_len);
        buf.putByte(R);
        buf.putByte(N);
        int j = 0;
        for (int i = 0; i < header_size; i++) {
            buf.put(encode_bytes_array.get(j++));
            buf.putByte((byte) ':');
            buf.putByte(SPACE);
            buf.put(encode_bytes_array.get(j++));
            buf.putByte(R);
            buf.putByte(N);
        }
        for (int i = 0; i < cookie_size; i++) {
            buf.put(encode_bytes_array.get(j++));
            buf.putByte((byte) ':');
            buf.put(encode_bytes_array.get(j++));
            buf.putByte((byte) ':');
        }
        buf.putByte(R);
        buf.putByte(N);
        if (write_size > 0) {
            if (isArray) {
                buf.put(contentArray);
            } else {
                ch.write(buf.flip());
                ch.write(contentBuf);
                return null;
            }
        }
        return buf.flip();
    }

    private String getRequestURI(HttpFrame frame) {
        Map params = frame.getRequestParams();
        if (params == null || params.isEmpty()) {
            return frame.getRequestURL();
        }
        String url = frame.getRequestURL();
        StringBuilder u = new StringBuilder(url);
        u.append("?");
        Set> ps = params.entrySet();
        for (Entry p : ps) {
            u.append(p.getKey());
            u.append("=");
            u.append(p.getValue());
            u.append("&");
        }
        return u.toString();
    }

    int onHeaderReadComplete(HttpFrame frame) throws IOException {
        ClientHttpFrame f = (ClientHttpFrame) frame;
        int contentLength = 0;
        String clength = f.getResponse(Content_Length);
        if (!Util.isNullOrBlank(clength)) {
            contentLength = Integer.parseInt(clength);
            f.setContentLength(contentLength);
        }
        if (contentLength < 1) {
            if (f.isChunked()) {
                return decode_state_body;
            } else {
                return decode_state_complate;
            }
        } else {
            if (contentLength > getBodyLimit()) {
                throw OVER_LIMIT;
            }
            return decode_state_body;
        }
    }

    @Override
    protected void parse_line_one(HttpFrame f, CharSequence line) {
        int index = Util.indexOf(line, ' ');
        int status = Integer.parseInt((String) line.subSequence(index + 1, index + 4));
        f.setVersion(HttpVersion.HTTP1_1.getId());
        f.setStatus(HttpStatus.get(status));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy