LCOV - code coverage report
Current view: top level - server - RequestInfo.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 42 42 100.0 %
Date: 2022-11-19 15:00:39 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2019 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server;
      16             : 
      17             : import static com.google.common.base.Preconditions.checkState;
      18             : import static java.util.Objects.requireNonNull;
      19             : 
      20             : import com.google.auto.value.AutoValue;
      21             : import com.google.auto.value.extension.memoized.Memoized;
      22             : import com.google.common.base.Splitter;
      23             : import com.google.gerrit.common.UsedAt;
      24             : import com.google.gerrit.entities.Project;
      25             : import com.google.gerrit.server.logging.TraceContext;
      26             : import java.util.Optional;
      27             : 
      28             : /** Information about a request that was received from a user. */
      29             : @AutoValue
      30         105 : public abstract class RequestInfo {
      31             :   /** Channel through which a user request was received. */
      32         105 :   public enum RequestType {
      33             :     /** request type for git push */
      34         105 :     GIT_RECEIVE,
      35             : 
      36             :     /** request type for git fetch */
      37         105 :     GIT_UPLOAD,
      38             : 
      39             :     /** request type for call to REST API */
      40         105 :     REST,
      41             : 
      42             :     /** request type for call to SSH API */
      43         105 :     SSH
      44             :   }
      45             : 
      46             :   /**
      47             :    * Type of the request, telling through which channel the request was coming in.
      48             :    *
      49             :    * <p>See {@link RequestType} for the types that are used by Gerrit core. Other request types are
      50             :    * possible, e.g. if a plugin supports receiving requests through another channel.
      51             :    */
      52             :   public abstract String requestType();
      53             : 
      54             :   /**
      55             :    * Request URI.
      56             :    *
      57             :    * <p>Only set if request type is {@link RequestType#REST}.
      58             :    *
      59             :    * <p>Never includes the "/a" prefix.
      60             :    */
      61             :   public abstract Optional<String> requestUri();
      62             : 
      63             :   /**
      64             :    * Redacted request URI.
      65             :    *
      66             :    * <p>Request URI where resource IDs are replaced by '*'.
      67             :    */
      68             :   @Memoized
      69             :   public Optional<String> redactedRequestUri() {
      70         105 :     return requestUri().map(RequestInfo::redactRequestUri);
      71             :   }
      72             : 
      73             :   /** The user that has sent the request. */
      74             :   public abstract CurrentUser callingUser();
      75             : 
      76             :   /** The trace context of the request. */
      77             :   public abstract TraceContext traceContext();
      78             : 
      79             :   /**
      80             :    * The name of the project for which the request is being done. Only available if the request is
      81             :    * tied to a project or change. If a project is available it's not guaranteed that it actually
      82             :    * exists (e.g. if a user made a request for a project that doesn't exist).
      83             :    */
      84             :   public abstract Optional<Project.NameKey> project();
      85             : 
      86             :   @Memoized
      87             :   public String formatForLogging() {
      88         105 :     StringBuilder sb = new StringBuilder();
      89         105 :     sb.append(requestType());
      90         105 :     redactedRequestUri().ifPresent(redactedRequestUri -> sb.append(' ').append(redactedRequestUri));
      91         105 :     return sb.toString();
      92             :   }
      93             : 
      94             :   /**
      95             :    * Redacts resource IDs from the given request URI.
      96             :    *
      97             :    * <p>resource IDs in the request URI are replaced with '*'.
      98             :    *
      99             :    * @param requestUri a REST URI that has path segments that alternate between view name and
     100             :    *     resource IDs (e.g. "/<view>", "/<view>/<id>", "/<view>/<id>/<view>",
     101             :    *     "/<view>/<id>/<view>/<id>", "/<view>/<id>/<view>/<id>/<view>" etc.), must be given without
     102             :    *     the '/a' prefix
     103             :    * @return the redacted request URI
     104             :    */
     105             :   static String redactRequestUri(String requestUri) {
     106          29 :     requireNonNull(requestUri, "requestUri");
     107          29 :     checkState(
     108          29 :         !requestUri.startsWith("/a/"), "request URI must not start with '/a/': %s", requestUri);
     109             : 
     110          29 :     StringBuilder redactedRequestUri = new StringBuilder();
     111             : 
     112          29 :     boolean hasLeadingSlash = false;
     113          29 :     boolean hasTrailingSlash = false;
     114          29 :     if (requestUri.startsWith("/")) {
     115          29 :       hasLeadingSlash = true;
     116          29 :       requestUri = requestUri.substring(1);
     117             :     }
     118          29 :     if (requestUri.endsWith("/")) {
     119          12 :       hasTrailingSlash = true;
     120          12 :       requestUri = requestUri.substring(0, requestUri.length() - 1);
     121             :     }
     122             : 
     123          29 :     boolean idPathSegment = false;
     124          29 :     for (String pathSegment : Splitter.on('/').split(requestUri)) {
     125          29 :       if (!idPathSegment) {
     126          29 :         redactedRequestUri.append("/" + pathSegment);
     127          29 :         idPathSegment = true;
     128             :       } else {
     129          28 :         redactedRequestUri.append("/");
     130          28 :         if (!pathSegment.isEmpty()) {
     131          28 :           redactedRequestUri.append("*");
     132             :         }
     133          28 :         idPathSegment = false;
     134             :       }
     135          29 :     }
     136             : 
     137          29 :     if (!hasLeadingSlash) {
     138           1 :       redactedRequestUri.deleteCharAt(0);
     139             :     }
     140          29 :     if (hasTrailingSlash) {
     141          12 :       redactedRequestUri.append('/');
     142             :     }
     143             : 
     144          29 :     return redactedRequestUri.toString();
     145             :   }
     146             : 
     147             :   public static RequestInfo.Builder builder(
     148             :       RequestType requestType, CurrentUser callingUser, TraceContext traceContext) {
     149         105 :     return builder().requestType(requestType).callingUser(callingUser).traceContext(traceContext);
     150             :   }
     151             : 
     152             :   @UsedAt(UsedAt.Project.GOOGLE)
     153             :   public static RequestInfo.Builder builder() {
     154         105 :     return new AutoValue_RequestInfo.Builder();
     155             :   }
     156             : 
     157             :   @AutoValue.Builder
     158         105 :   public abstract static class Builder {
     159             :     public abstract Builder requestType(String requestType);
     160             : 
     161             :     public Builder requestType(RequestType requestType) {
     162         105 :       return requestType(requestType.name());
     163             :     }
     164             : 
     165             :     public abstract Builder requestUri(String requestUri);
     166             : 
     167             :     public abstract Builder callingUser(CurrentUser callingUser);
     168             : 
     169             :     public abstract Builder traceContext(TraceContext traceContext);
     170             : 
     171             :     public abstract Builder project(Project.NameKey projectName);
     172             : 
     173             :     public abstract RequestInfo build();
     174             :   }
     175             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750