blob: 7aae8e3b595aab3d22cf342393f35870e4b3c287 [file] [log] [blame]
Remi NGUYEN VAN7995b432020-08-14 12:49:56 +09001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.testutils
18
19import android.net.Uri
20import com.android.net.module.util.ArrayTrackRecord
21import fi.iki.elonen.NanoHTTPD
22
23/**
24 * A minimal HTTP server running on a random available port.
25 *
26 * @param host The host to listen to, or null to listen on all hosts
27 */
28class TestHttpServer(host: String? = null) : NanoHTTPD(host, 0 /* auto-select the port */) {
29 // Map of URL path -> HTTP response code
30 private val responses = HashMap<Request, Response>()
31
32 /**
33 * A record of all requests received by the server since it was started.
34 */
35 val requestsRecord = ArrayTrackRecord<Request>()
36
37 /**
38 * A request received by the test server.
39 */
40 data class Request(
41 val path: String,
42 val method: Method = Method.GET,
43 val queryParameters: String = ""
44 ) {
45 /**
46 * Returns whether the specified [Uri] matches parameters of this request.
47 */
48 fun matches(uri: Uri) = (uri.path ?: "") == path && (uri.query ?: "") == queryParameters
49 }
50
51 /**
52 * Add a response for GET requests with the path and query parameters of the specified [Uri].
53 */
54 fun addResponse(
55 uri: Uri,
56 statusCode: Response.IStatus,
57 locationHeader: String? = null,
58 content: String = ""
59 ) {
60 addResponse(Request(uri.path
61 ?: "", Method.GET, uri.query ?: ""),
62 statusCode, locationHeader, content)
63 }
64
65 /**
66 * Add a response for the given request.
67 */
68 fun addResponse(
69 request: Request,
70 statusCode: Response.IStatus,
71 locationHeader: String? = null,
72 content: String = ""
73 ) {
74 val response = newFixedLengthResponse(statusCode, "text/plain", content)
75 locationHeader?.let { response.addHeader("Location", it) }
76 responses[request] = response
77 }
78
79 override fun serve(session: IHTTPSession): Response {
80 val request = Request(session.uri
81 ?: "", session.method, session.queryParameterString ?: "")
82 requestsRecord.add(request)
83 // Default response is a 404
84 return responses[request] ?: super.serve(session)
85 }
86}