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

com.uber.tchannel.messages.Response Maven / Gradle / Ivy

/*
 * Copyright (c) 2015 Uber Technologies, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.uber.tchannel.messages;

import com.uber.tchannel.api.ResponseCode;
import com.uber.tchannel.errors.ErrorType;
import com.uber.tchannel.frames.FrameType;
import com.uber.tchannel.headers.ArgScheme;
import com.uber.tchannel.headers.TransportHeaders;
import com.uber.tchannel.utils.TChannelUtilities;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;

/**
 * Represents a TChannel response message with `raw` arg scheme encoding.
 * 

* All RPC frames over TChannel contain 3 opaque byte payloads, namely, arg{1,2,3}. TChannel makes no assumptions * about the contents of these frames. In order to make sense of these arg payloads, TChannel has the notion of * `arg messages` which define standardized schemas and serialization formats over the raw arg{1,2,3} payloads. The * supported `arg messages` are `thrift`, `json`, `http` and `sthrift`. These request / response frames will be built * on top of {@link RawRequest} and {@link Response} frames. *

*

From the Docs

* The `raw` encoding is intended for any custom encodings you want to do that * are not part of TChannel but are application specific. */ public abstract class Response extends ResponseMessage implements RawMessage { private static final @NotNull ByteBuf arg1 = TChannelUtilities.emptyByteBuf; protected @Nullable ByteBuf arg2; protected @Nullable ByteBuf arg3; protected long id; protected final @Nullable ResponseCode responseCode; protected final @Nullable Map transportHeaders; private final @Nullable ErrorResponse error; protected Response( long id, ResponseCode responseCode, Map transportHeaders, ByteBuf arg2, ByteBuf arg3 ) { this.id = id; this.responseCode = responseCode; this.transportHeaders = transportHeaders; this.arg2 = arg2; this.arg3 = arg3; this.type = FrameType.CallResponse; this.error = null; } protected Response(@NotNull Builder builder) { this.id = builder.id; this.responseCode = builder.responseCode; this.transportHeaders = builder.transportHeaders; this.arg2 = builder.arg2; this.arg3 = builder.arg3; this.type = FrameType.CallResponse; this.error = null; } protected Response(@NotNull ErrorResponse error) { this.id = error.getId(); this.responseCode = null; this.transportHeaders = null; this.arg2 = null; this.arg3 = null; this.type = FrameType.Error; this.error = error; } @Override public long getId() { return this.id; } public void setId(long id) { this.id = id; } public @Nullable ResponseCode getResponseCode() { return responseCode; } @Override public @Nullable Map getTransportHeaders() { return this.transportHeaders; } @Override public @NotNull ByteBuf getArg1() { return arg1; } @Override public @Nullable ByteBuf getArg2() { return arg2; } @Override public @Nullable ByteBuf getArg3() { return arg3; } @Override public String toString() { return String.format( "<%s id=%d transportHeaders=%s arg1=%s arg2=%s arg3=%s>", getClass().getSimpleName(), id, transportHeaders, arg1.toString(CharsetUtil.UTF_8), arg2 == null ? null : arg2.toString(CharsetUtil.UTF_8), arg3 == null ? null : arg3.toString(CharsetUtil.UTF_8) ); } @Override public void release() { arg1.release(); if (arg2 != null) { arg2.release(); arg2 = null; } if (arg3 != null) { arg3.release(); arg3 = null; } } @Override public boolean isError() { return type == FrameType.Error || getError() != null; } public @Nullable ErrorResponse getError() { return this.error; } public ArgScheme getArgScheme() { return ArgScheme.toScheme(transportHeaders.get(TransportHeaders.ARG_SCHEME_KEY)); } public int argSize() { return (arg2 == null ? 0 : arg2.readableBytes()) + (arg3 == null ? 0 : arg3.readableBytes()); } public static @Nullable Response build( long id, ResponseCode responseCode, @NotNull Map transportHeaders, ByteBuf arg2, ByteBuf arg3 ) { ArgScheme argScheme = ArgScheme.toScheme(transportHeaders.get(TransportHeaders.ARG_SCHEME_KEY)); if (argScheme == null) { return null; } return Response.build(argScheme, id, responseCode, transportHeaders, arg2, arg3); } public static @Nullable Response build( @NotNull ArgScheme argScheme, long id, ResponseCode responseCode, Map transportHeaders, ByteBuf arg2, ByteBuf arg3 ) { final Response res; switch (argScheme) { case RAW: res = new RawResponse(id, responseCode, transportHeaders, arg2, arg3); break; case JSON: res = new JsonResponse<>(id, responseCode, transportHeaders, arg2, arg3); break; case THRIFT: res = new ThriftResponse<>(id, responseCode, transportHeaders, arg2, arg3); break; default: res = null; break; } return res; } public static @NotNull Response build(@NotNull ArgScheme argScheme, long id, ErrorType errorType, String message) { return build(argScheme, new ErrorResponse(id, errorType, message)); } public static @NotNull Response build(@NotNull ArgScheme argScheme, ErrorResponse errorResponse) { final Response res; switch (argScheme) { case RAW: res = new RawResponse(errorResponse); break; case JSON: res = new JsonResponse<>(errorResponse); break; case THRIFT: res = new ThriftResponse<>(errorResponse); break; default: res = new RawResponse(errorResponse); break; } return res; } public static class Builder { protected @NotNull Map transportHeaders = new HashMap<>(); protected ByteBuf arg2 = null; protected ByteBuf arg3 = null; protected ResponseCode responseCode = ResponseCode.OK; private long id = -1; public Builder(@NotNull Request req) { this.id = req.getId(); this.transportHeaders.put( TransportHeaders.ARG_SCHEME_KEY, req.getTransportHeaders().get(TransportHeaders.ARG_SCHEME_KEY) ); } public @NotNull Builder setResponseCode(ResponseCode responseCode) { this.responseCode = responseCode; return this; } public @NotNull Builder setArg2(ByteBuf arg2) { if (this.arg2 != null) { this.arg2.release(); } this.arg2 = arg2; return this; } public @NotNull Builder setArg3(ByteBuf arg3) { if (this.arg3 != null) { this.arg3.release(); } this.arg3 = arg3; return this; } public @NotNull Builder setTransportHeader(String key, String value) { this.transportHeaders.put(key, value); return this; } public @NotNull Builder setTransportHeaders(@NotNull Map transportHeaders) { this.transportHeaders = transportHeaders; return this; } public @NotNull Builder setId(long id) { this.id = id; return this; } public @NotNull Builder validate() { return this; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy