
org.apache.kafka.common.requests.RequestHeader Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.kafka.common.requests;
import org.apache.kafka.common.errors.InvalidRequestException;
import org.apache.kafka.common.protocol.ApiKeys;
import org.apache.kafka.common.protocol.types.Field;
import org.apache.kafka.common.protocol.types.Schema;
import org.apache.kafka.common.protocol.types.Struct;
import java.nio.ByteBuffer;
import static java.util.Objects.requireNonNull;
import static org.apache.kafka.common.protocol.types.Type.INT16;
import static org.apache.kafka.common.protocol.types.Type.INT32;
import static org.apache.kafka.common.protocol.types.Type.NULLABLE_STRING;
/**
* The header for a request in the Kafka protocol
*/
public class RequestHeader extends AbstractRequestResponse {
private static final String API_KEY_FIELD_NAME = "api_key";
private static final String API_VERSION_FIELD_NAME = "api_version";
private static final String CLIENT_ID_FIELD_NAME = "client_id";
private static final String CORRELATION_ID_FIELD_NAME = "correlation_id";
public static final Schema SCHEMA = new Schema(
new Field(API_KEY_FIELD_NAME, INT16, "The id of the request type."),
new Field(API_VERSION_FIELD_NAME, INT16, "The version of the API."),
new Field(CORRELATION_ID_FIELD_NAME, INT32, "A user-supplied integer value that will be passed back with the response"),
new Field(CLIENT_ID_FIELD_NAME, NULLABLE_STRING, "A user specified identifier for the client making the request.", ""));
// Version 0 of the controlled shutdown API used a non-standard request header (the clientId is missing).
// This can be removed once we drop support for that version.
private static final Schema CONTROLLED_SHUTDOWN_V0_SCHEMA = new Schema(
new Field(API_KEY_FIELD_NAME, INT16, "The id of the request type."),
new Field(API_VERSION_FIELD_NAME, INT16, "The version of the API."),
new Field(CORRELATION_ID_FIELD_NAME, INT32, "A user-supplied integer value that will be passed back with the response"));
private final ApiKeys apiKey;
private final short apiVersion;
private final String clientId;
private final int correlationId;
public RequestHeader(Struct struct) {
short apiKey = struct.getShort(API_KEY_FIELD_NAME);
if (!ApiKeys.hasId(apiKey))
throw new InvalidRequestException("Unknown API key " + apiKey);
this.apiKey = ApiKeys.forId(apiKey);
apiVersion = struct.getShort(API_VERSION_FIELD_NAME);
// only v0 of the controlled shutdown request is missing the clientId
if (struct.hasField(CLIENT_ID_FIELD_NAME))
clientId = struct.getString(CLIENT_ID_FIELD_NAME);
else
clientId = "";
correlationId = struct.getInt(CORRELATION_ID_FIELD_NAME);
}
public RequestHeader(ApiKeys apiKey, short version, String clientId, int correlation) {
this.apiKey = requireNonNull(apiKey);
this.apiVersion = version;
this.clientId = clientId;
this.correlationId = correlation;
}
public Struct toStruct() {
Schema schema = schema(apiKey.id, apiVersion);
Struct struct = new Struct(schema);
struct.set(API_KEY_FIELD_NAME, apiKey.id);
struct.set(API_VERSION_FIELD_NAME, apiVersion);
// only v0 of the controlled shutdown request is missing the clientId
if (struct.hasField(CLIENT_ID_FIELD_NAME))
struct.set(CLIENT_ID_FIELD_NAME, clientId);
struct.set(CORRELATION_ID_FIELD_NAME, correlationId);
return struct;
}
public ApiKeys apiKey() {
return apiKey;
}
public short apiVersion() {
return apiVersion;
}
public String clientId() {
return clientId;
}
public int correlationId() {
return correlationId;
}
public ResponseHeader toResponseHeader() {
return new ResponseHeader(correlationId);
}
public static RequestHeader parse(ByteBuffer buffer) {
try {
short apiKey = buffer.getShort();
short apiVersion = buffer.getShort();
Schema schema = schema(apiKey, apiVersion);
buffer.rewind();
return new RequestHeader(schema.read(buffer));
} catch (InvalidRequestException e) {
throw e;
} catch (Throwable ex) {
throw new InvalidRequestException("Error parsing request header. Our best guess of the apiKey is: " +
buffer.getShort(0), ex);
}
}
@Override
public String toString() {
return "RequestHeader(apiKey=" + apiKey +
", apiVersion=" + apiVersion +
", clientId=" + clientId +
", correlationId=" + correlationId +
")";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RequestHeader that = (RequestHeader) o;
return apiKey == that.apiKey &&
apiVersion == that.apiVersion &&
correlationId == that.correlationId &&
(clientId == null ? that.clientId == null : clientId.equals(that.clientId));
}
@Override
public int hashCode() {
int result = apiKey.hashCode();
result = 31 * result + (int) apiVersion;
result = 31 * result + (clientId != null ? clientId.hashCode() : 0);
result = 31 * result + correlationId;
return result;
}
private static Schema schema(short apiKey, short version) {
if (apiKey == ApiKeys.CONTROLLED_SHUTDOWN.id && version == 0)
// This will be removed once we remove support for v0 of ControlledShutdownRequest, which
// depends on a non-standard request header (it does not have a clientId)
return CONTROLLED_SHUTDOWN_V0_SCHEMA;
return SCHEMA;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy