2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.asuswrt.internal.api;
15 import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.JSON_MEMBER_TOKEN;
16 import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.*;
17 import static org.openhab.binding.asuswrt.internal.constants.AsuswrtErrorConstants.*;
18 import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.getValueOrDefault;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.TimeoutException;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.eclipse.jetty.client.HttpResponse;
26 import org.eclipse.jetty.client.api.ContentResponse;
27 import org.eclipse.jetty.client.api.Request;
28 import org.eclipse.jetty.client.api.Result;
29 import org.eclipse.jetty.client.util.BufferingResponseListener;
30 import org.eclipse.jetty.client.util.StringContentProvider;
31 import org.eclipse.jetty.http.HttpMethod;
32 import org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils;
33 import org.openhab.binding.asuswrt.internal.things.AsuswrtRouter;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 import com.google.gson.Gson;
38 import com.google.gson.JsonObject;
41 * The {@link AsuswrtHttpClient} is used for (a)synchronous HTTP requests.
43 * @author Christian Wild - Initial contribution
46 public class AsuswrtHttpClient {
47 private final Logger logger = LoggerFactory.getLogger(AsuswrtHttpClient.class);
48 private Gson gson = new Gson();
49 protected AsuswrtRouter router;
50 protected final String uid;
51 public AsuswrtCookie cookieStore = new AsuswrtCookie();
53 public AsuswrtHttpClient(AsuswrtRouter router) {
55 uid = router.getUID().toString();
63 * Sends a synchronous HTTP request.
65 * The result will be handled in {@link #handleHttpSuccessResponse(String, String)} or
66 * {@link #handleHttpResultError(Throwable)}.
68 * If the response should be returned use {@link #getSyncRequest(String, String)} instead.
70 * @param url the URL the request is sent to
71 * @param payload the payload to send
72 * @param command the command to perform
74 protected void sendSyncRequest(String url, String payload, String command) {
75 ContentResponse response = getSyncRequest(url, payload);
76 if (response != null) {
77 handleHttpSuccessResponse(response.getContentAsString(), command);
82 * Sends a synchronous HTTP request.
84 * @param url the URL the request is sent to
85 * @param payload the payload to send
86 * @return {@link ContentResponse} of the request
88 protected @Nullable ContentResponse getSyncRequest(String url, String payload) {
89 logger.trace("({}) sendRequest '{}' to '{}' with cookie '{}'", uid, payload, url, cookieStore.getCookie());
90 Request httpRequest = this.router.getHttpClient().newRequest(url).method(HttpMethod.POST.toString());
93 httpRequest = setHeaders(httpRequest);
94 httpRequest.timeout(HTTP_TIMEOUT_MS, TimeUnit.MILLISECONDS);
97 httpRequest.content(new StringContentProvider(payload, HTTP_CONTENT_CHARSET), HTTP_CONTENT_TYPE);
99 return httpRequest.send();
100 } catch (Exception e) {
101 handleHttpResultError(e);
107 * Sends an asynchronous HTTP request so it does not wait for an answer.
109 * The result will be handled in {@link #handleHttpSuccessResponse(String, String)} or
110 * {@link #handleHttpResultError(Throwable)}.
112 * @param url the URL to which the request is sent to
113 * @param payload the payload data
114 * @param command command to execute, this will handle ResponseType
116 protected void sendAsyncRequest(String url, String payload, String command) {
117 logger.trace("({}) sendAsyncRequest to '{}' with cookie '{}'", uid, url, cookieStore.getCookie());
119 Request httpRequest = router.getHttpClient().newRequest(url).method(HttpMethod.POST.toString());
122 httpRequest = setHeaders(httpRequest);
125 httpRequest.content(new StringContentProvider(payload, HTTP_CONTENT_CHARSET), HTTP_CONTENT_TYPE);
127 httpRequest.timeout(HTTP_TIMEOUT_MS, TimeUnit.MILLISECONDS).send(new BufferingResponseListener() {
128 @NonNullByDefault({})
130 public void onComplete(Result result) {
131 final HttpResponse response = (HttpResponse) result.getResponse();
132 if (result.getFailure() != null) {
133 // Handle result errors
134 handleHttpResultError(result.getFailure());
135 } else if (response.getStatus() != 200) {
136 logger.debug("({}) sendAsyncRequest response error '{}'", uid, response.getStatus());
137 router.errorHandler.raiseError(ERR_RESPONSE, getContentAsString());
139 // Request successful
140 String rBody = getContentAsString();
141 logger.trace("({}) requestCompleted '{}'", uid, rBody);
143 handleHttpSuccessResponse(rBody, command);
147 } catch (Exception e) {
148 router.errorHandler.raiseError(e);
155 private Request setHeaders(Request httpRequest) {
157 httpRequest.header("content-type", HTTP_CONTENT_TYPE);
158 httpRequest.header("user-agent", HTTP_USER_AGENT);
159 if (cookieStore.isValid()) {
160 httpRequest.header("cookie", cookieStore.getCookie());
170 * Handles HTTP result failures.
172 * @param e the exception
173 * @param payload full payload for debugging
175 protected void handleHttpResultError(Throwable e, String payload) {
176 String errorMessage = getValueOrDefault(e.getMessage(), "");
178 if (e instanceof TimeoutException) {
179 logger.debug("({}) sendAsyncRequest timeout'{}'", uid, errorMessage);
180 } else if (e instanceof InterruptedException) {
181 logger.debug("({}) sending request interrupted: {}", uid, e.toString());
183 logger.debug("({}) sendAsyncRequest failed'{}'", uid, errorMessage);
187 protected void handleHttpResultError(Throwable e) {
188 handleHttpResultError(e, "");
192 * Handles a successful HTTP response.
194 * @param responseBody response body as string
195 * @param command command constant which was sent
197 protected void handleHttpSuccessResponse(String responseBody, String command) {
201 * Sets a cookie from a response.
203 protected void setCookieFromResponse(ContentResponse response) {
204 cookieStore.resetCookie();
205 if (response.getStatus() == 200) {
206 String rBody = response.getContentAsString();
207 logger.trace("({}) received response '{}'", uid, rBody);
209 /* get json object 'asus_token' */
210 JsonObject jsonObject = gson.fromJson(rBody, JsonObject.class);
211 if (jsonObject != null && jsonObject.has(JSON_MEMBER_TOKEN)) {
212 String token = jsonObject.get(JSON_MEMBER_TOKEN).getAsString();
213 this.cookieStore.setCookie("asus_token=" + token);
215 } catch (Exception e) {
216 logger.debug("({}) {} on login request '{}'", uid, ERR_RESPONSE, e.getMessage());
217 router.errorHandler.raiseError(ERR_RESPONSE, e.getMessage());
220 String reason = AsuswrtUtils.getValueOrDefault(response.getReason(), "");
221 router.errorHandler.raiseError(ERR_RESPONSE, reason);
226 * Gets JSON from a response.
228 protected JsonObject getJsonFromResponse(ContentResponse response) {
229 return getJsonFromString(response.getContentAsString());
233 * Gets JSON from a response.
235 protected JsonObject getJsonFromString(String responseBody) {
237 JsonObject jsonObject = gson.fromJson(responseBody, JsonObject.class);
238 logger.trace("({}) received result: {}", uid, responseBody);
239 /* get error code (0=success) */
240 if (jsonObject != null) {
243 } catch (Exception e) {
244 logger.debug("({}) {} {}", uid, ERR_JSON_FORMAT, responseBody);
245 router.getErrorHandler().raiseError(e);
247 return new JsonObject();