/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.testutils import android.net.Uri import com.android.net.module.util.ArrayTrackRecord import fi.iki.elonen.NanoHTTPD /** * A minimal HTTP server running on a random available port. * * @param host The host to listen to, or null to listen on all hosts */ class TestHttpServer(host: String? = null) : NanoHTTPD(host, 0 /* auto-select the port */) { // Map of URL path -> HTTP response code private val responses = HashMap() /** * A record of all requests received by the server since it was started. */ val requestsRecord = ArrayTrackRecord() /** * A request received by the test server. */ data class Request( val path: String, val method: Method = Method.GET, val queryParameters: String = "" ) { /** * Returns whether the specified [Uri] matches parameters of this request. */ fun matches(uri: Uri) = (uri.path ?: "") == path && (uri.query ?: "") == queryParameters } /** * Add a response for GET requests with the path and query parameters of the specified [Uri]. */ fun addResponse( uri: Uri, statusCode: Response.IStatus, locationHeader: String? = null, content: String = "" ) { addResponse(Request(uri.path ?: "", Method.GET, uri.query ?: ""), statusCode, locationHeader, content) } /** * Add a response for the given request. */ fun addResponse( request: Request, statusCode: Response.IStatus, locationHeader: String? = null, content: String = "" ) { val response = newFixedLengthResponse(statusCode, "text/plain", content) locationHeader?.let { response.addHeader("Location", it) } responses[request] = response } override fun serve(session: IHTTPSession): Response { val request = Request(session.uri ?: "", session.method, session.queryParameterString ?: "") requestsRecord.add(request) // Default response is a 404 return responses[request] ?: super.serve(session) } }