View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2025 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.jcabi.http.mock;
6   
7   import com.jcabi.aspects.Immutable;
8   import com.jcabi.http.ImmutableHeader;
9   import com.jcabi.immutable.ArrayMap;
10  import java.io.ByteArrayOutputStream;
11  import java.io.IOException;
12  import java.io.InputStream;
13  import java.net.URI;
14  import java.nio.charset.StandardCharsets;
15  import java.util.Arrays;
16  import java.util.Collections;
17  import java.util.LinkedList;
18  import java.util.List;
19  import java.util.Map;
20  import java.util.concurrent.ConcurrentHashMap;
21  import java.util.concurrent.ConcurrentMap;
22  import org.glassfish.grizzly.http.Method;
23  import org.glassfish.grizzly.http.server.Request;
24  
25  /**
26   * Mock HTTP query/request.
27   *
28   * @since 0.10
29   */
30  @Immutable
31  final class GrizzlyQuery implements MkQuery {
32  
33      /**
34       * HTTP request method.
35       */
36      private final transient Method mtd;
37  
38      /**
39       * HTTP request content.
40       */
41      @Immutable.Array
42      private final transient byte[] content;
43  
44      /**
45       * HTTP request URI.
46       */
47      private final transient String home;
48  
49      /**
50       * HTTP request headers.
51       */
52      private final transient ArrayMap<String, List<String>> hdrs;
53  
54      /**
55       * Ctor.
56       * @param request Grizzly request
57       * @throws IOException If fails
58       */
59      @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors")
60      GrizzlyQuery(final Request request) throws IOException {
61          request.setCharacterEncoding(StandardCharsets.UTF_8.toString());
62          this.home = GrizzlyQuery.uri(request);
63          this.mtd = request.getMethod();
64          this.hdrs = GrizzlyQuery.headers(request);
65          this.content = GrizzlyQuery.input(request);
66      }
67  
68      @Override
69      public URI uri() {
70          return URI.create(this.home);
71      }
72  
73      @Override
74      public String method() {
75          return this.mtd.getMethodString();
76      }
77  
78      @Override
79      public Map<String, List<String>> headers() {
80          return Collections.unmodifiableMap(this.hdrs);
81      }
82  
83      @Override
84      public String body() {
85          return new String(this.content, StandardCharsets.UTF_8);
86      }
87  
88      @Override
89      public byte[] binary() {
90          return Arrays.copyOf(this.content, this.content.length);
91      }
92  
93      /**
94       * Fetch URI from the request.
95       * @param request Request
96       * @return URI
97       */
98      private static String uri(final Request request) {
99          final StringBuilder uri = new StringBuilder(request.getRequestURI());
100         final String query = request.getQueryString();
101         if (query != null && !query.isEmpty()) {
102             uri.append('?').append(query);
103         }
104         return uri.toString();
105     }
106 
107     /**
108      * Fetch headers from the request.
109      * @param request Request
110      * @return Headers
111      */
112     private static ArrayMap<String, List<String>> headers(
113         final Request request
114     ) {
115         final ConcurrentMap<String, List<String>> headers =
116             new ConcurrentHashMap<>(0);
117         final Iterable<String> names = request.getHeaderNames();
118         for (final String name : names) {
119             headers.put(
120                 ImmutableHeader.normalize(name),
121                 GrizzlyQuery.headers(request, name)
122             );
123         }
124         return new ArrayMap<>(headers);
125     }
126 
127     /**
128      * Get headers by name.
129      * @param request Grizzly request
130      * @param name Name of header
131      * @return List of values
132      */
133     private static List<String> headers(
134         final Request request, final String name
135     ) {
136         final List<String> list = new LinkedList<>();
137         final Iterable<?> values = request.getHeaders(name);
138         for (final Object value : values) {
139             list.add(value.toString());
140         }
141         return list;
142     }
143 
144     /**
145      * Read req.
146      * @param req Grizzly req
147      * @return Bytes of input
148      * @throws IOException If fails
149      */
150     private static byte[] input(final Request req) throws IOException {
151         // @checkstyle MagicNumber (1 line)
152         final byte[] buffer = new byte[8192];
153         final ByteArrayOutputStream output;
154         try (InputStream input = req.getInputStream()) {
155             output = new ByteArrayOutputStream();
156             while (true) {
157                 final int bytes = input.read(buffer);
158                 if (bytes == -1) {
159                     break;
160                 }
161                 output.write(buffer, 0, bytes);
162             }
163         }
164         return output.toByteArray();
165     }
166 }