001/*
002 * Copyright 2022-2026 Revetware LLC.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.soklet;
018
019import org.jspecify.annotations.NonNull;
020
021/**
022 * Policy used by the standard HTTP server to decide whether an eligible response should be gzipped.
023 * <p>
024 * Soklet invokes this policy only after its own HTTP protocol checks pass. For example,
025 * {@code Accept-Encoding} must permit {@code gzip}, and Soklet will skip streaming, file,
026 * range, already-encoded, transfer-encoded, bodyless, and otherwise ineligible responses.
027 * Implementations must be thread-safe; the standard HTTP server may invoke the policy concurrently
028 * from request-handling threads.
029 *
030 * @author <a href="https://www.revetkn.com">Mark Allen</a>
031 */
032@FunctionalInterface
033public interface ResponseGzipPolicy {
034        /**
035         * Acquires a policy that disables response gzip.
036         *
037         * @return a disabled response gzip policy
038         */
039        @NonNull
040        static ResponseGzipPolicy disabledInstance() {
041                return DisabledResponseGzipPolicy.defaultInstance();
042        }
043
044        /**
045         * Acquires a policy that gzips common text-like response media types when the finalized body is
046         * at least {@code minimumBodySizeInBytes}.
047         * <p>
048         * The default media-type set includes {@code text/*}, {@code application/json},
049         * {@code application/*+json}, {@code application/xml}, {@code application/*+xml},
050         * {@code application/javascript}, {@code application/graphql}, {@code application/x-www-form-urlencoded},
051         * and {@code image/svg+xml}.
052         *
053         * @param minimumBodySizeInBytes the minimum finalized body size to gzip
054         * @return a default response gzip policy
055         */
056        @NonNull
057        static ResponseGzipPolicy fromDefaultsWithMinimumBodySizeInBytes(@NonNull Integer minimumBodySizeInBytes) {
058                return new DefaultResponseGzipPolicy(minimumBodySizeInBytes);
059        }
060
061        /**
062         * Decides whether an eligible response should be gzipped.
063         * <p>
064         * Returning {@code true} permits gzip; returning {@code false} writes the response unchanged.
065         *
066         * @param request the request being handled
067         * @param response the finalized response being written
068         * @return {@code true} to gzip the response, or {@code false} to write it unchanged
069         */
070        @NonNull
071        Boolean shouldGzip(@NonNull Request request,
072                                                                                 @NonNull MarshaledResponse response);
073}