1 /*
2  * Copyright (C) 2022 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 
17 package android.webkit.cts;
18 
19 import static org.junit.Assert.fail;
20 
21 import android.os.Bundle;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import org.apache.http.Header;
26 import org.apache.http.HttpEntity;
27 import org.apache.http.HttpEntityEnclosingRequest;
28 import org.apache.http.util.EntityUtils;
29 
30 import java.io.IOException;
31 import java.util.ArrayList;
32 import java.util.Locale;
33 
34 /**
35  * This class attempts to match the Apache HttpRequest as close as possible so that it can be used
36  * in place of it. The apache HttpRequest is not parcelable.
37  */
38 public class HttpRequest implements Parcelable {
39     private final Locale mLowerCaseLocale = Locale.forLanguageTag("en-US");
40     private Bundle mHeaders;
41     private String mUrl;
42     private String mMethod;
43     private String mBody;
44 
45     public static final Parcelable.Creator<HttpRequest> CREATOR =
46             new Parcelable.Creator<HttpRequest>() {
47                 public HttpRequest createFromParcel(Parcel in) {
48                     return new HttpRequest(in);
49                 }
50 
51                 public HttpRequest[] newArray(int size) {
52                     return new HttpRequest[size];
53                 }
54             };
55 
HttpRequest(String url, org.apache.http.HttpRequest apacheRequest)56     public HttpRequest(String url, org.apache.http.HttpRequest apacheRequest) {
57         mHeaders = new Bundle();
58         mUrl = url;
59         mMethod = apacheRequest.getRequestLine().getMethod();
60         mBody = null;
61 
62         try {
63             if (apacheRequest instanceof HttpEntityEnclosingRequest) {
64                 HttpEntity entity = ((HttpEntityEnclosingRequest) apacheRequest).getEntity();
65                 mBody = EntityUtils.toString(entity);
66             }
67         } catch (IOException err) {
68             fail("Failed to request request body");
69         }
70 
71         for (Header header : apacheRequest.getAllHeaders()) {
72             ArrayList<String> headerValues = mHeaders.getStringArrayList(header.getName());
73             if (headerValues == null) {
74                 headerValues = new ArrayList<String>();
75             }
76 
77             headerValues.add(header.getValue());
78             // Http Headers are case insensitive so storing all headers as lowercase.
79             // Lowercasing by locale to avoid the infamous turkish locale bug.
80             mHeaders.putStringArrayList(
81                     header.getName().toLowerCase(mLowerCaseLocale), headerValues);
82         }
83     }
84 
HttpRequest(Parcel in)85     HttpRequest(Parcel in) {
86         // Note: This must be read in the same order we write
87         // to the parcel in {@link #wroteToParcel(Parcel out, int flags)}.
88         mHeaders = in.readBundle();
89         mUrl = in.readString();
90         mMethod = in.readString();
91         mBody = in.readString();
92     }
93 
94     @Override
writeToParcel(Parcel out, int flags)95     public void writeToParcel(Parcel out, int flags) {
96         // Note: This must be written in the same order we read
97         // from the parcel in {@link #HttpRequest(Parcel in)}.
98         out.writeBundle(mHeaders);
99         out.writeString(mUrl);
100         out.writeString(mMethod);
101         out.writeString(mBody);
102     }
103 
104     @Override
describeContents()105     public int describeContents() {
106         return 0;
107     }
108 
109     /** Retrieve all the headers for the URL request matching a header string. */
getHeaders(String header)110     public String[] getHeaders(String header) {
111         ArrayList<String> headers =
112                 mHeaders.getStringArrayList(header.toLowerCase(mLowerCaseLocale));
113         if (headers != null) {
114             return headers.toArray(new String[] {});
115         }
116         return new String[] {};
117     }
118 
119     /** Returns the url of the request. */
getUrl()120     public String getUrl() {
121         return mUrl;
122     }
123 
124     /** Returns the method of the request. */
getMethod()125     public String getMethod() {
126         return mMethod;
127     }
128 
129     /** Returns the body of the request. */
getBody()130     public String getBody() {
131         return mBody;
132     }
133 }
134