| 2035 | } |
| 2036 | |
| 2037 | public CompletableFuture<Object> fetch(Object url2, Object method2, Object headers2, Object body2) { |
| 2038 | if (this.fetchResponse != null) { |
| 2039 | return CompletableFuture.completedFuture(this.fetchResponse); |
| 2040 | } |
| 2041 | ensureHttpClientUpToDate(); |
| 2042 | |
| 2043 | String url = (String) url2; |
| 2044 | String method = (String) method2; |
| 2045 | @SuppressWarnings("unchecked") |
| 2046 | Map<String, Object> headersArg = (headers2 instanceof Map) ? (Map<String, Object>) headers2 : null; |
| 2047 | @SuppressWarnings("unchecked") |
| 2048 | Map<String, Object> headers = (Map<String, Object>) this.extend(this.headers, headersArg); |
| 2049 | String body = (String) body2; |
| 2050 | |
| 2051 | Object proxyUrlObj = this.checkProxyUrlSettings(url, method, headers, body); |
| 2052 | if (proxyUrlObj != null) { |
| 2053 | String proxyUrl = proxyUrlObj.toString(); |
| 2054 | url = proxyUrl + this.urlEncoderForProxyUrl(url).toString(); |
| 2055 | } |
| 2056 | |
| 2057 | if (this.verbose) { |
| 2058 | this.log( |
| 2059 | "fetch Request:\n" |
| 2060 | + this.id + " " + method + " " + url |
| 2061 | + "\nRequestHeaders:\n" + this.json(headers) |
| 2062 | + "\nRequestBody:\n" + this.json(body) + "\n" |
| 2063 | ); |
| 2064 | } |
| 2065 | |
| 2066 | this.checkProxySettings(url, method, headers, body); |
| 2067 | |
| 2068 | List<String> headerKeys = new java.util.ArrayList<>(headers.keySet()); |
| 2069 | String contentType = ""; |
| 2070 | |
| 2071 | HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); |
| 2072 | // Java's URI.create is strict (RFC 3986) and rejects characters like |
| 2073 | // ", |, {, }, ^, `, <, > in the query, even though Node fetch / axios |
| 2074 | // accept them. Some exchanges (e.g. coinsph parseArrayParam) emit |
| 2075 | // partially-encoded queries — `?symbols=%5B"BTCUSDT"%5D` — that round- |
| 2076 | // trip through TS but throw URISyntaxException here. Percent-encode |
| 2077 | // any remaining illegal chars before parsing. |
| 2078 | requestBuilder.uri(URI.create(escapeIllegalUriChars(url))); |
| 2079 | |
| 2080 | // Apply HTTP timeout |
| 2081 | if (this.timeout != null) { |
| 2082 | long timeoutMs; |
| 2083 | if (this.timeout instanceof Number) { |
| 2084 | timeoutMs = ((Number) this.timeout).longValue(); |
| 2085 | } else { |
| 2086 | timeoutMs = Long.parseLong(this.timeout.toString()); |
| 2087 | } |
| 2088 | if (timeoutMs > 0) { |
| 2089 | requestBuilder.timeout(java.time.Duration.ofMillis(timeoutMs)); |
| 2090 | } |
| 2091 | } |
| 2092 | |
| 2093 | if (this.userAgent != null && this.userAgent.length() > 0) { |
| 2094 | requestBuilder.header("User-Agent", this.userAgent); |