- Особенности HttpUrlConnection из java.net
- Class HttpURLConnection
- Field Summary
- Fields declared in class java.net.URLConnection
- Constructor Summary
- Method Summary
- Methods declared in class java.net.URLConnection
- Methods declared in class java.lang.Object
- Field Details
- method
- chunkLength
- fixedContentLength
- fixedContentLengthLong
- responseCode
- responseMessage
- instanceFollowRedirects
- HTTP_OK
- HTTP_CREATED
- HTTP_ACCEPTED
- HTTP_NOT_AUTHORITATIVE
- HTTP_NO_CONTENT
- HTTP_RESET
- HTTP_PARTIAL
- HTTP_MULT_CHOICE
- HTTP_MOVED_PERM
- HTTP_MOVED_TEMP
- HTTP_SEE_OTHER
- HTTP_NOT_MODIFIED
- HTTP_USE_PROXY
- HTTP_BAD_REQUEST
- HTTP_UNAUTHORIZED
- HTTP_PAYMENT_REQUIRED
- HTTP_FORBIDDEN
- HTTP_NOT_FOUND
- HTTP_BAD_METHOD
- HTTP_NOT_ACCEPTABLE
- HTTP_PROXY_AUTH
- HTTP_CLIENT_TIMEOUT
- HTTP_CONFLICT
- HTTP_GONE
- HTTP_LENGTH_REQUIRED
- HTTP_PRECON_FAILED
- HTTP_ENTITY_TOO_LARGE
- HTTP_REQ_TOO_LONG
- HTTP_UNSUPPORTED_TYPE
- HTTP_SERVER_ERROR
- HTTP_INTERNAL_ERROR
- HTTP_NOT_IMPLEMENTED
- HTTP_BAD_GATEWAY
- HTTP_UNAVAILABLE
- HTTP_GATEWAY_TIMEOUT
- HTTP_VERSION
- Constructor Details
- HttpURLConnection
- Method Details
- setAuthenticator
- getHeaderFieldKey
- setFixedLengthStreamingMode
- setFixedLengthStreamingMode
- setChunkedStreamingMode
- getHeaderField
- setFollowRedirects
- getFollowRedirects
- setInstanceFollowRedirects
- getInstanceFollowRedirects
- setRequestMethod
Особенности HttpUrlConnection из java.net
сегодня постараюсь рассказать о том, как можно отправить запрос и прочитать ответ от HTTP сервера, используя URLConnection из библиотеки JRE.
- users.list
- chat.postMessage
- conversations.create
- files.upload
- im.open
GET /users.list HTTP/1.1 Content-Type: application/x-www-form-urlencoded token=xoxp-1234567890-098765-4321-a1b2c3d4e5
Я знал про библиотеку Apache HttpComponents, но для иследовательских целей будем использовать средства доступные в стандартной библиотеке Java 8, а именно имплементацию java.net.URLConnection.
Для получений сущности URLConnection нужно использовать объект класса java.net.URL, его конструктор принимает тип String где помимо всего должен быть указан протокол – в нашем случае https.
После получения сущности URL, вызываем метод openConnection() который возвратит нам сущность HttpsUrlConnection.
String url = “https://slack.com/api/users.list”; URLConnection connection = new URL(url).openConnection();
При этом нужно обработать или пробросить MalformedUrlException и IOException.
После этого переменная connection будет хранить ссылку на объект HttpsUrlConnectionImpl. По умолчанию будет формироваться GET-запрос, для того чтобы добавить Header используем метод setRequestProperty(), который принимает key и value. Нам здесь нужно установить Content-Type который имеет значение application/x-www-form-urlencoded. Ну, и мы это делаем!
connection.setRequestProperty(“Content-Type”, “application/x-www-form-urlencoded”);
Теперь осталось только отправить запрос записав в тело наш токен и лимит. Для этого нужно установить поле doOutput объекта connection в положение true, используя метод setDoOutput();
connection.setDoOutput(true);
Далее самая интересная часть — нужно как-то передать наше тело запроса в OutputStream. Будем использовать OutputStreamWriter:
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
Есть один нюанс: после того, как мы вызвали метод getOutputStream() метод запроса меняется на POST, так как GET не предусматривает наличие request body, но благо что slack ни ставит твёрдое ограничение на метод поэтому всё было хорошо. И поэтому GET-запрос должен выглядеть так:
GET /users.list?token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100 HTTP/1.1 Content-Type: application/x-www-form-urlencoded
Но я не стал уже переделывать. И вместо этого наш запрос получился таким:
POST /users.list HTTP/1.1 Content-Type: application/x-www-form-urlencoded token=xoxp-1234567890-098765-4321-a1b2c3d4e5
(*некоторые headers ставятся самим HttpsUrlConnection и здесь они отсутствуют)
И так чтоб записать наше тело запроса пользуемся write();.
String reqBody = “token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100”; writer.write(reqBody); writer.close();
После этого наш запрос будет отправлен, и мы можем прочитать полученный ответ. Важно закрывать OutputStream или делать flush(), перед тем как получать InputStream, иначе данные не уйдут из буффера(как альтернатива можно использовать PrintStream — в методе println() по умолчанию вызывается flush()). Для чтение использовал BufferedReader:
StringBuilder respBody = new StringBuilder(); BufferedReader reader = new BufferedReader(connection.getInputStream()); reader.lines().forEach(l -> respBody.append(l + “\r\n”); reader.close();
(*используем lines() чтобы получить Stream на выходе; \r\n – символ CRLF – вставляет переход на новую строку)
И, если мы успешно проходим аутентификацию, переменная respBody должна хранить наш ответ от сервера, что в нашем случае является JSON объектом. После этого, его можно отправлять на следующий этап обработки.
После некоторой оптимизации всё выглядет так:
package main.java.com.bilichenko.learning; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.Charset; import java.util.Optional; import java.util.stream.Collectors; public class SlackClient < private static final String HOST = "https://api.slack.com"; private static final String GET_USERS_URI = "/api/users.list"; private static final String TOKEN = "xx-ooo-YOUR-TOKEN-HERE"; public static void main(String[] args) throws IOException < SlackClient slackClient = new SlackClient(); System.out.println(slackClient.getRawResponse(HOST + GET_USERS_URI, "application/x-www-form-urlencoded", "token=" + TOKEN).orElse("no response")); >public Optional getRawResponse(String url, String contentType, String requestBody) throws MalformedURLException, IOException < HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestProperty("Content-Type", contentType); connection.setConnectTimeout(10000); connection.setRequestMethod("POST"); connection.setDoOutput(true); try(OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream())) < writer.write(requestBody); >if (connection.getResponseCode() != 200) < System.err.println("connection failed"); return Optional.empty(); >try(BufferedReader reader = new BufferedReader( new InputStreamReader(connection.getInputStream(), Charset.forName("utf-8")))) < return Optional.of(reader.lines().collect(Collectors.joining(System.lineSeparator()))); >> >
Class HttpURLConnection
Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances. Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.
The HTTP protocol handler has a few settings that can be accessed through System Properties. This covers Proxy settings as well as various other settings.
- a «connect» SocketPermission to the host/port combination of the destination URL or
- a URLPermission that permits this request.
If automatic redirection is enabled, and this request is redirected to another destination, then the caller must also have permission to connect to the redirected host/URL.
Field Summary
Fields declared in class java.net.URLConnection
Constructor Summary
Method Summary
Returns a SocketPermission object representing the permission necessary to connect to the destination host and port.
Supplies an Authenticator to be used when authentication is requested through the HTTP protocol for this HttpURLConnection .
This method is used to enable streaming of a HTTP request body without internal buffering, when the content length is not known in advance.
This method is used to enable streaming of a HTTP request body without internal buffering, when the content length is known in advance.
This method is used to enable streaming of a HTTP request body without internal buffering, when the content length is known in advance.
Sets whether HTTP redirects (requests with response code 3xx) should be automatically followed by this class.
Sets whether HTTP redirects (requests with response code 3xx) should be automatically followed by this HttpURLConnection instance.
Set the method for the URL request, one of: GET POST HEAD OPTIONS PUT DELETE TRACE are legal, subject to protocol restrictions.
Methods declared in class java.net.URLConnection
Methods declared in class java.lang.Object
Field Details
method
chunkLength
The chunk-length when using chunked encoding streaming mode for output. A value of -1 means chunked encoding is disabled for output.
fixedContentLength
The fixed content-length when using fixed-length streaming mode. A value of -1 means fixed-length streaming mode is disabled for output. NOTE: fixedContentLengthLong is recommended instead of this field, as it allows larger content lengths to be set.
fixedContentLengthLong
The fixed content-length when using fixed-length streaming mode. A value of -1 means fixed-length streaming mode is disabled for output.
responseCode
- 1xx: Informational
- 2xx: Success
- 3xx: Redirection
- 4xx: Client Error
- 5xx: Server Error
responseMessage
instanceFollowRedirects
If true , the protocol will automatically follow redirects. If false , the protocol will not automatically follow redirects. This field is set by the setInstanceFollowRedirects method. Its value is returned by the getInstanceFollowRedirects method. Its default value is based on the value of the static followRedirects at HttpURLConnection construction time.
HTTP_OK
HTTP_CREATED
HTTP_ACCEPTED
HTTP_NOT_AUTHORITATIVE
HTTP_NO_CONTENT
HTTP_RESET
HTTP_PARTIAL
HTTP_MULT_CHOICE
HTTP_MOVED_PERM
HTTP_MOVED_TEMP
HTTP_SEE_OTHER
HTTP_NOT_MODIFIED
HTTP_USE_PROXY
HTTP_BAD_REQUEST
HTTP_UNAUTHORIZED
HTTP_PAYMENT_REQUIRED
HTTP_FORBIDDEN
HTTP_NOT_FOUND
HTTP_BAD_METHOD
HTTP_NOT_ACCEPTABLE
HTTP_PROXY_AUTH
HTTP_CLIENT_TIMEOUT
HTTP_CONFLICT
HTTP_GONE
HTTP_LENGTH_REQUIRED
HTTP_PRECON_FAILED
HTTP_ENTITY_TOO_LARGE
HTTP_REQ_TOO_LONG
HTTP_UNSUPPORTED_TYPE
HTTP_SERVER_ERROR
HTTP_INTERNAL_ERROR
HTTP_NOT_IMPLEMENTED
HTTP_BAD_GATEWAY
HTTP_UNAVAILABLE
HTTP_GATEWAY_TIMEOUT
HTTP_VERSION
Constructor Details
HttpURLConnection
Method Details
setAuthenticator
Supplies an Authenticator to be used when authentication is requested through the HTTP protocol for this HttpURLConnection . If no authenticator is supplied, the default authenticator will be used.
getHeaderFieldKey
Returns the key for the n th header field. Some implementations may treat the 0 th header field as special, i.e. as the status line returned by the HTTP server. In this case, getHeaderField(0) returns the status line, but getHeaderFieldKey(0) returns null.
setFixedLengthStreamingMode
This method is used to enable streaming of a HTTP request body without internal buffering, when the content length is known in advance. An exception will be thrown if the application attempts to write more data than the indicated content-length, or if the application closes the OutputStream before writing the indicated amount. When output streaming is enabled, authentication and redirection cannot be handled automatically. A HttpRetryException will be thrown when reading the response if authentication or redirection are required. This exception can be queried for the details of the error. This method must be called before the URLConnection is connected. NOTE: setFixedLengthStreamingMode(long) is recommended instead of this method as it allows larger content lengths to be set.
setFixedLengthStreamingMode
This method is used to enable streaming of a HTTP request body without internal buffering, when the content length is known in advance. An exception will be thrown if the application attempts to write more data than the indicated content-length, or if the application closes the OutputStream before writing the indicated amount. When output streaming is enabled, authentication and redirection cannot be handled automatically. A HttpRetryException will be thrown when reading the response if authentication or redirection are required. This exception can be queried for the details of the error. This method must be called before the URLConnection is connected. The content length set by invoking this method takes precedence over any value set by setFixedLengthStreamingMode(int) .
setChunkedStreamingMode
This method is used to enable streaming of a HTTP request body without internal buffering, when the content length is not known in advance. In this mode, chunked transfer encoding is used to send the request body. Note, not all HTTP servers support this mode. When output streaming is enabled, authentication and redirection cannot be handled automatically. A HttpRetryException will be thrown when reading the response if authentication or redirection are required. This exception can be queried for the details of the error. This method must be called before the URLConnection is connected.
getHeaderField
Returns the value for the n th header field. Some implementations may treat the 0 th header field as special, i.e. as the status line returned by the HTTP server. This method can be used in conjunction with the getHeaderFieldKey method to iterate through all the headers in the message.
setFollowRedirects
Sets whether HTTP redirects (requests with response code 3xx) should be automatically followed by this class. True by default. Applets cannot change this variable. If there is a security manager, this method first calls the security manager’s checkSetFactory method to ensure the operation is allowed. This could result in a SecurityException.
getFollowRedirects
setInstanceFollowRedirects
Sets whether HTTP redirects (requests with response code 3xx) should be automatically followed by this HttpURLConnection instance. The default value comes from followRedirects, which defaults to true.