OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 180 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
177 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
185 ilm 4
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
177 ilm 5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.utils.net;
15
 
185 ilm 16
import org.openconcerto.utils.StreamUtils;
17
 
177 ilm 18
import java.io.IOException;
19
import java.io.InputStream;
20
import java.io.OutputStream;
21
import java.net.URL;
22
import java.nio.charset.StandardCharsets;
23
import java.util.Base64;
24
import java.util.Set;
25
import java.util.zip.GZIPInputStream;
26
import java.util.zip.GZIPOutputStream;
27
 
28
import javax.net.ssl.HttpsURLConnection;
29
import javax.net.ssl.SSLSocketFactory;
30
 
31
public class HTTPClient {
32
 
33
    private static final int MIN_GZIP_SIZE = 64;
34
 
35
    static public class ServerException extends RuntimeException {
36
        private final int responseCode;
37
        private final boolean authenticateError;
38
 
185 ilm 39
        private ServerException(final String message, final int responseCode, final boolean authenticateError) {
40
            super(message);
177 ilm 41
            this.responseCode = responseCode;
42
            this.authenticateError = authenticateError;
43
        }
44
 
185 ilm 45
        protected ServerException(int responseCode, boolean authenticateError) {
46
            this("Response code was " + responseCode, responseCode, authenticateError);
47
        }
48
 
49
        protected ServerException(Response response, String errorBody, boolean authenticateError) {
50
            this(response.toString() + (errorBody == null ? "" : "\n" + errorBody), response.getCode(), authenticateError);
51
        }
52
 
177 ilm 53
        public final int getResponseCode() {
54
            return this.responseCode;
55
        }
56
 
57
        public final boolean isAuthenticateError() {
58
            return this.authenticateError;
59
        }
60
    }
61
 
62
    static public final class Response {
63
 
64
        protected final static Response create(HttpsURLConnection con, final Set<Integer> okCodes) throws IOException {
65
            final boolean success = okCodes == null ? con.getResponseCode() == 200 : okCodes.contains(con.getResponseCode());
185 ilm 66
            return new Response(con.getURL().toExternalForm(), success, con.getResponseCode(), con.getResponseMessage(), con.getContentEncoding(), con.getContentType());
177 ilm 67
        }
68
 
185 ilm 69
        private final String url;
177 ilm 70
        private final boolean success;
71
        private final int code;
72
        private final String message;
73
        private final String contentEncoding, contentType;
74
 
185 ilm 75
        protected Response(final String url, boolean success, int code, String message, String contentEncoding, String contentType) {
177 ilm 76
            super();
185 ilm 77
            this.url = url;
177 ilm 78
            this.success = success;
79
            this.code = code;
80
            this.message = message;
81
            this.contentEncoding = contentEncoding;
82
            this.contentType = contentType;
83
        }
84
 
185 ilm 85
        public final String getURL() {
86
            return this.url;
87
        }
88
 
177 ilm 89
        public final int getCode() {
90
            return this.code;
91
        }
92
 
93
        public final boolean isSuccess() {
94
            return this.success;
95
        }
96
 
97
        public final String getMessage() {
98
            return this.message;
99
        }
100
 
101
        public final String getContentEncoding() {
102
            return this.contentEncoding;
103
        }
104
 
105
        public final String getContentType() {
106
            return this.contentType;
107
        }
185 ilm 108
 
109
        @Override
110
        public String toString() {
111
            return this.getClass().getSimpleName() + (this.isSuccess() ? " SUCCESS (" : " ERROR (") + this.getCode() + ") \"" + this.getMessage() + "\" to " + this.url;
112
        }
177 ilm 113
    }
114
 
115
    private final String url;
116
    private SSLSocketFactory socketFactory;
117
    private String token;
118
    private boolean throwException = true;
119
 
120
    public HTTPClient(final String url) {
121
        this.url = url;
122
    }
123
 
185 ilm 124
    public final String getURL() {
125
        return this.url;
126
    }
127
 
177 ilm 128
    public final SSLSocketFactory getSocketFactory() {
129
        return this.socketFactory;
130
    }
131
 
132
    public final void setSocketFactory(SSLSocketFactory socketFactory) {
133
        this.socketFactory = socketFactory;
134
    }
135
 
136
    public final void setToken(String token) {
137
        this.token = token;
138
    }
139
 
140
    public final boolean hasToken() {
141
        return this.getToken() != null;
142
    }
143
 
180 ilm 144
    public final String getToken() {
177 ilm 145
        return this.token;
146
    }
147
 
148
    public final void setThrowException(boolean throwException) {
149
        this.throwException = throwException;
150
    }
151
 
152
    public final boolean throwsException() {
153
        return this.throwException;
154
    }
155
 
156
    public final Response checkResponseCode(final HttpsURLConnection con) throws IOException {
157
        return checkResponseCode(con, null);
158
    }
159
 
160
    public final Response checkResponseCode(final HttpsURLConnection con, final Set<Integer> okCodes) throws IOException {
161
        final Response res = Response.create(con, okCodes);
185 ilm 162
        if (this.throwsException() && !res.isSuccess()) {
163
            final String errorBody;
164
            try (final InputStream errorStream = con.getErrorStream()) {
165
                errorBody = errorStream == null ? null : new String(StreamUtils.read(errorStream), StandardCharsets.UTF_8);
166
            }
167
            throw new ServerException(res, errorBody, con.getHeaderField("WWW-Authenticate") != null);
168
        }
177 ilm 169
        return res;
170
    }
171
 
172
    public final HttpsURLConnection openConnection(final String path) throws IOException {
173
        final HttpsURLConnection con = (HttpsURLConnection) new URL(this.url + path).openConnection();
174
        con.setRequestProperty("Accept-Encoding", "gzip");
175
        if (this.getSocketFactory() != null)
176
            con.setSSLSocketFactory(this.getSocketFactory());
180 ilm 177
        if (getToken() != null) {
177 ilm 178
            con.setRequestProperty("Authorization", "Bearer " + Base64.getEncoder().encodeToString(getToken().getBytes(StandardCharsets.UTF_8)));
180 ilm 179
        }
177 ilm 180
        return con;
181
    }
182
 
183
    public final InputStream getInputStream(final HttpsURLConnection con) throws IOException {
184
        return "gzip".equals(con.getContentEncoding()) ? new GZIPInputStream(con.getInputStream()) : con.getInputStream();
185
    }
186
 
180 ilm 187
    public final HttpsURLConnection send(final HttpsURLConnection con, final String formUrlEncodedParams) throws IOException {
188
        return this.send(con, formUrlEncodedParams, true);
177 ilm 189
    }
190
 
180 ilm 191
    public final HttpsURLConnection send(final HttpsURLConnection con, final String formUrlEncodedParams, final boolean allowGzip) throws IOException {
192
        con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
193
        return this.send(con, formUrlEncodedParams.getBytes(StandardCharsets.UTF_8), allowGzip);
177 ilm 194
    }
195
 
196
    public final HttpsURLConnection send(final HttpsURLConnection con, final byte[] toSend, final boolean allowGzip) throws IOException {
197
        final boolean useGzip = allowGzip && toSend.length >= MIN_GZIP_SIZE;
198
        if (useGzip)
199
            con.setRequestProperty("Content-Encoding", "gzip");
200
        con.setRequestMethod("POST");
201
        con.setDoOutput(true);
202
        try (final OutputStream o = useGzip ? new GZIPOutputStream(con.getOutputStream()) : con.getOutputStream()) {
203
            o.write(toSend);
204
        }
205
        return con;
206
    }
207
}