# 发起请求

网络解锁器作为HTTP代理运行，并对流量执行中间人（MITM）操作。这使其能够拦截和修改请求，从而绕过反爬保护。

由于MITM机制和所需的SSL处理，不建议在浏览器或Playwright等工具中使用该解锁器。

基于工具特性，我们目前仅支持**GET**请求。

**請求範例：**

{% tabs %}
{% tab title="cURL" %}
{% code overflow="wrap" %}

```
curl -k -v -x http://unblocker.iproyal.com:12323 --proxy-user username:password -L https://ipv4.icanhazip.com
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}

```php
<?php

declare(strict_types=1);

$url = 'https://ipv4.icanhazip.com';
$proxy = 'http://unblocker.iproyal.com:12323';
$proxyAuth = 'username:password';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyAuth);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

$response = curl_exec($ch);
curl_close($ch);

echo $response;
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = 'https://ipv4.icanhazip.com'
proxy = 'unblocker.iproyal.com:12323'
proxy_auth = 'username:password'
proxies = {
   'http': f'http://{proxy_auth}@{proxy}',
   'https': f'http://{proxy_auth}@{proxy}'
}

response = requests.get(
   url,
   proxies=proxies,
   verify=False,
   allow_redirects=True,
   timeout=30,
)
print(response.text)
```

{% endtab %}

{% tab title="Node.js" %}

```
const { fetch, ProxyAgent } = require('undici');

const url = 'https://ipv4.icanhazip.com';
const client = new ProxyAgent(
  'http://username:password@unblocker.iproyal.com:12323'
);

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

(async () => {
  try {
    const response = await fetch(url, {
      redirect: 'follow',
      dispatcher: client,
      headers: {
        'user-agent': 'undici-proxy-test'
      }
    });
    const text = await response.text();
    if (!response.ok) {
      console.error(`HTTP ${response.status} ${response.statusText}`);
    }
    console.log(text.trim());
  } catch (error) {
    console.error('Fetch failed:', error);
  }
})();
```

{% endtab %}

{% tab title="Java" %}

```java
import javax.net.ssl.*;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Main {
    private static final String PROXY_HOST = "unblocker.iproyal.com";
    private static final int    PROXY_PORT = 12323;
    private static final String USERNAME   = "username";
    private static final String PASSWORD   = "password";

    private static final String TARGET_HOST = "ipv4.icanhazip.com";
    private static final int    TARGET_PORT = 443;

    private static final boolean INSECURE_TRUST_ALL = true;

    public static void main(String[] args) {
        try {
            System.out.println(fetchIpThroughProxy());
        } catch (Exception e) {
            System.err.println("ERROR: " + e.getClass().getSimpleName() + ": " + e.getMessage());
        }
    }

    private static String fetchIpThroughProxy() throws Exception {
        final String basic = Base64.getEncoder()
                .encodeToString((USERNAME + ":" + PASSWORD).getBytes(StandardCharsets.ISO_8859_1));

        try (Socket proxy = new Socket()) {
            proxy.connect(new InetSocketAddress(PROXY_HOST, PROXY_PORT), 15_000);
            proxy.setSoTimeout(15_000);

            try (var out = new BufferedWriter(new OutputStreamWriter(proxy.getOutputStream(), StandardCharsets.ISO_8859_1));
                 var in  = new BufferedInputStream(proxy.getInputStream())) {

                out.write("CONNECT " + TARGET_HOST + ":" + TARGET_PORT + " HTTP/1.1\r\n");
                out.write("Host: " + TARGET_HOST + ":" + TARGET_PORT + "\r\n");
                out.write("Proxy-Authorization: Basic " + basic + "\r\n");
                out.write("Proxy-Connection: Keep-Alive\r\n\r\n");
                out.flush();

                final String status = readLine(in);
                if (status == null || !status.startsWith("HTTP/1.1 200")) {
                    throw new IOException("CONNECT failed: " + status);
                }
                drainHeaders(in);

                SSLSocket ssl = (SSLSocket) sslFactory().createSocket(proxy, TARGET_HOST, TARGET_PORT, true);
                SSLParameters params = ssl.getSSLParameters();
                params.setServerNames(java.util.List.of(new SNIHostName(TARGET_HOST)));
                ssl.setSSLParameters(params);
                ssl.startHandshake();

                try (var httpsOut = new BufferedWriter(new OutputStreamWriter(ssl.getOutputStream(), StandardCharsets.ISO_8859_1));
                     var httpsIn  = new BufferedInputStream(ssl.getInputStream())) {

                    httpsOut.write("GET / HTTP/1.1\r\n");
                    httpsOut.write("Host: " + TARGET_HOST + "\r\n");
                    httpsOut.write("User-Agent: JavaRawProxy\r\n");
                    httpsOut.write("Connection: close\r\n\r\n");
                    httpsOut.flush();

                    drainHeaders(httpsIn);
                    return readBody(httpsIn).trim();
                }
            }
        }
    }

    private static SSLSocketFactory sslFactory() throws Exception {
        if (!INSECURE_TRUST_ALL) return (SSLSocketFactory) SSLSocketFactory.getDefault();
        TrustManager[] trustAll = new TrustManager[]{ new X509TrustManager() {
            public void checkClientTrusted(java.security.cert.X509Certificate[] c, String a) {}
            public void checkServerTrusted(java.security.cert.X509Certificate[] c, String a) {}
            public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; }
        }};
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(null, trustAll, new java.security.SecureRandom());
        return ctx.getSocketFactory();
    }

    private static void drainHeaders(InputStream in) throws IOException {
        String line;
        while ((line = readLine(in)) != null && !line.isEmpty()) {}
    }

    private static String readBody(InputStream in) throws IOException {
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        byte[] tmp = new byte[4096];
        int n;
        while ((n = in.read(tmp)) != -1) buf.write(tmp, 0, n);
        return buf.toString(StandardCharsets.ISO_8859_1);
    }

    private static String readLine(InputStream in) throws IOException {
        StringBuilder sb = new StringBuilder();
        int prev = -1, cur;
        while ((cur = in.read()) != -1) {
            if (prev == '\r' && cur == '\n') { sb.setLength(sb.length() - 1); break; }
            sb.append((char) cur); prev = cur;
        }
        return (sb.length() == 0 && cur == -1) ? null : sb.toString();
    }
}
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
    "crypto/tls"
    "encoding/base64"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "time"
)

func main() {
    proxyUser := "username"
    proxyPass := "password"
    proxyStr := "http://unblocker.iproyal.com:12323"

    target := "https://ipv4.icanhazip.com"

    proxyURL, err := url.Parse(proxyStr)
    if err != nil {
        panic(err)
    }
    proxyURL.User = url.UserPassword(proxyUser, proxyPass)

    basic := "Basic " + base64.StdEncoding.EncodeToString([]byte(proxyUser+":"+proxyPass))

    tr := &http.Transport{
        Proxy: http.ProxyURL(proxyURL),

        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},

        ProxyConnectHeader: http.Header{
            "Proxy-Authorization": []string{basic},
        },
    }

    client := &http.Client{
        Transport: tr,
        Timeout:   30 * time.Second,
    }

    resp, err := client.Get(target)
    if err != nil {
        fmt.Println("Request error:", err)
        return
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    fmt.Printf("HTTP %d\n%s\n", resp.StatusCode, string(body))
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Text;

class Program
{
    static async Task Main()
    {
        var url = new Uri("https://ipv4.icanhazip.com");
        var proxy = new Uri("http://unblocker.iproyal.com:12323");
        const string proxyUser = "username";
        const string proxyPass = "password";

        using var client = CreateHttpClient(proxy, proxyUser, proxyPass);
        var ip = (await client.GetStringAsync(url)).Trim();
        Console.WriteLine(ip);
    }

    private static HttpClient CreateHttpClient(Uri proxyUri, string user, string pass)
    {
        var handler = new SocketsHttpHandler
        {
            AllowAutoRedirect = true,
            AutomaticDecompression = DecompressionMethods.All,
            SslOptions = new SslClientAuthenticationOptions
            {
                RemoteCertificateValidationCallback = static (_, _, _, _) => true
            },
            ConnectCallback = async (ctx, ct) =>
            {
                var tcp = new TcpClient();
                await tcp.ConnectAsync(proxyUri.Host, proxyUri.Port);
                var stream = tcp.GetStream();

                var auth = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{user}:{pass}"));
                string host = ctx.DnsEndPoint.Host;
                int port = ctx.DnsEndPoint.Port;

                var request =
                    $"CONNECT {host}:{port} HTTP/1.1\r\n" +
                    $"Host: {host}:{port}\r\n" +
                    $"Proxy-Authorization: Basic {auth}\r\n" +
                    "\r\n";

                var bytes = Encoding.ASCII.GetBytes(request);
                await stream.WriteAsync(bytes, 0, bytes.Length, ct);
                await stream.FlushAsync(ct);

                using var reader = new StreamReader(stream, Encoding.ASCII, detectEncodingFromByteOrderMarks: false, bufferSize: 4096, leaveOpen: true);
                var status = await reader.ReadLineAsync();
                if (status is null || !status.Contains(" 200 "))
                    throw new IOException($"Proxy CONNECT failed: {status}");
                
                while (!string.IsNullOrEmpty(await reader.ReadLineAsync())) { }
                return stream;
            }
        };

        var client = new HttpClient(handler)
        {
            Timeout = TimeSpan.FromSeconds(30)
        };
        client.DefaultRequestVersion = HttpVersion.Version11;
        return client;
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
使用网络解锁器时，**必须禁用 HTTPS 证书验证。**
{% endhint %}

**响应代码**

错误代码（通常为HTTP状态码）表示在访问网站时遇到的问题。

常见错误代码包括404（未找到）、403（禁止访问）、502（错误网关）和503（服务不可用）。这些代码有助于确定问题是出在客户端（4xx）、服务器端（5xx）还是重定向（3xx）。

| **响应代码** | **说明**                      |
| -------- | --------------------------- |
| 200      | 请求成功。                       |
| 301/302  | 页面已重定向。                     |
| 403      | 请求被拦截。                      |
| 404      | URL不存在。                     |
| 429      | 达到速率限制。我们目前允许同时最多有200个活跃连接。 |
| 500      | 目标服务器出现问题。                  |
| 502      | 网关或代理服务器未能获取有效响应。           |
| 503      | 服务器过载或停机。                   |
| 504      | 服务器响应超时。                    |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.iproyal.com/cn/gong-ju/wang-luo-jie-suo-qi/fa-qi-qing-qiu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
