> For the complete documentation index, see [llms.txt](https://javascriptuse.gitbook.io/advanced/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://javascriptuse.gitbook.io/advanced/3.-proxy.md).

# 3. Proxy

## 3. Proxy <a href="#id-3-proxy-5" id="id-3-proxy-5"></a>

Về mặt ý tưởng đây có lẽ là cách đơn giản nhất. Nếu như không được phép thực hiện cross-domain AJAX request thì chúng ta chuyển sang same-domain request (haha). Nguyên lý là chúng ta sẽ chuẩn bị một proxy server đặt tại domain giống với domain gửi AJAX request, proxy này có nhiệm vụ nhận request và chuyển hướng request sang domain bên ngoài. Do thực hiện request đến domain bên ngoài ở phía server nên chúng ta sẽ không gặp phải bất kì hạn chế nào liên quan đến same-origin policy.

![Proxy](https://viblo.asia/uploads/9f3efb29-81ee-47d4-94e5-f8f4d3d0d728.png)

Việc chuẩn bị một proxy nói chung là phức tạp nhưng để demo cách thức hoạt động của phương pháp này mình xin được đưa ra 1 ví dụ với Rails. Đây là 1 cách implement đơn giản, proxy thực chất là một controller đặt tại `http://my-domain.com/ajax`, có nhiệm vụ nhận và chuyển hướng request đến `http://other-domain.com`.

```
# routes.rb
match "ajax/:path", to: 'ajax#create', via: :all, constraints: {path: /.*/}
```

```
class AjaxController < ActionController::Base
  skip_before_action :verify_authenticity_token

  def create
    # get request url
    path = params[:path].split('/').map{|i| ERB::Util.url_encode(i)}.join('/')
    url = 'http://other-domain.com' + '/' + path

    # remove some unnecessary parameters
    data = params.except(:controller, :action, :path)

    # get custom headers
    request_headers = {
      'CustomHeader' => request.headers['CustomHeader']
    }

    # send cross-domain request
    case env['REQUEST_METHOD']
    when 'GET'
      response = RestClient.get(url + '?' + data.to_query, request_headers)
    when 'POST'
      response = RestClient.post(url, data, request_headers)
    when 'PUT', 'PATCH'
      response = RestClient.put(url, data, request_headers)
    when 'DELETE'
      response = RestClient.delete(url + '?' + data.to_query, request_headers)
    end

    # return response
    render html: response.body.html_safe
  end
end
```

Khi gửi AJAX request thì chúng ta chỉ cần thay đổi url là được, lúc này request đã trở thành same-domain request (yeah)

```
$.ajax({
  url: 'http://my-domain.com/ajax/data'
})
```

#### **Ưu điểm và nhược điểm** <a href="#uu-diem-va-nhuoc-diem-6" id="uu-diem-va-nhuoc-diem-6"></a>

Ưu điểm:

* Sử dụng được với tất cả các browser
* Gửi được request với tất cả các loại HTTP method
* Gửi được custom header kèm theo

Nhược điểm

* Implement ở phía server phức tạp
* Tốc độ chậm do phải request 2 lần

## Tổng kết <a href="#tong-ket-7" id="tong-ket-7"></a>

### `tl;dr` <a href="#tldr-8" id="tldr-8"></a>

Bài viết cũng đã khá dài nên có lẽ xin được kết thúc tại đây. Thay cho lời kết, mình xin tổng kết lại các đặc điểm của từng phương pháp trong bảng dưới để các bạn tiện tham khảo.

|                        | JSONP     | CORS (XMLHttpRequest) | CORS (XDomainRequest) | Proxy     |
| ---------------------- | --------- | --------------------- | --------------------- | --------- |
| Implement phía client  | Đơn giản  | Đơn giản              | Đơn giản              | Không cần |
| Implement phía server  | Đơn giản  | Đơn giản              | Đơn giản              | Phức tạp  |
| Các trình duyệt hỗ trợ | Tất cả    | Hầu hết               | IE 8, 9               | Tất cả    |
| HTTP method            | GET       | Tất cả                | GET, POST             | Tất cả    |
| Gửi kèm header         | Không thể | Có thể                | Có thể (\*)           | Có thể    |

(\*) Không thể gửi custom header

Cảm ơn các bạn đã theo dõi bài viết. (thanks)

#### Tài liệu tham khảo <a href="#tai-lieu-tham-khao-9" id="tai-lieu-tham-khao-9"></a>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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://javascriptuse.gitbook.io/advanced/3.-proxy.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.
