syntax = "proto3";

// If you make any changes make sure you run: make regenerate-proto

package gitlab.agent.prototool;

option go_package = "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/prototool";
import "buf/validate/validate.proto";

// NOTE: HeaderValues and HeaderKV use bytes for values because HTTP
// allows binary values in header values.
// See https://www.rfc-editor.org/rfc/rfc9110.html#name-field-values.
// keys are bytes too because we don't need to pay the price of "is UTF-8?" validation, we run manual
// and more strict validation instead.

message HeaderValues {
  // At least one item, but it can be empty.
  repeated bytes value = 1 [
    (buf.validate.field).repeated.min_items = 1

    // TODO add validation here once the bytes.matches works as required. See https://github.com/bufbuild/protovalidate/issues/268.
    // This is not an issue because stdlib's HTTP server drops headers with invalid names and filters out invalid
    // bytes from header values.

    // See https://github.com/golang/go/blob/go1.23.2/src/net/http/header.go#L198-L204
    // See https://github.com/golang/go/blob/go1.23.2/src/net/http/header.go#L206-L207.

//    (buf.validate.field).repeated.items.bytes.pattern = "^[^\\x00-\\x08\\x0A-\\x1F\\x7F]*$"
  ];
}

// This is a map<> key-value entry as a message.
// We don't use map<> because we want key as bytes, which is not allowed in map<>.
// See https://protobuf.dev/programming-guides/proto3/#backwards
message HeaderKV {
  bytes key = 1 [(buf.validate.field).bytes.pattern = "^:?[0-9a-zA-Z!#$%&'*+-.^_|~`]+$"];
  HeaderValues value = 2 [(buf.validate.field).required = true];
}

// Query parameters.
message QueryValues {
  repeated bytes value = 1; // Items may be empty and there may be no items.
}

// This is a map<> key-value entry as a message.
// We don't use map<> because we want key as bytes, which is not allowed in map<>.
// See https://protobuf.dev/programming-guides/proto3/#backwards
message QueryKV {
  bytes key = 1 [(buf.validate.field).bytes.min_len = 1];
  QueryValues value = 2 [(buf.validate.field).required = true];
}

message HttpRequest {
  // HTTP method.
  string method = 1 [(buf.validate.field).string.min_bytes = 1];
  // HTTP header.
  repeated HeaderKV header = 2;
  // URL path. Should start with a slash.
  string url_path = 3 [(buf.validate.field).string.min_bytes = 1];
  // query is the URL query part.
  repeated QueryKV query = 4;
}

message HttpResponse {
  // HTTP status code.
  int32 status_code = 1;
  // HTTP status message.
  string status = 2;
  // HTTP header.
  repeated HeaderKV header = 3;
}
