Cách ngăn chặn yêu cầu ajax đi theo chuyển hướng bằng jQuery


102

Tôi sử dụng các hàm ajax của jQuery để truy cập dịch vụ web, nhưng máy chủ, thay vì trả về phản hồi có mã trạng thái mô tả sự cố, yêu cầu được chuyển hướng đến trang có tiêu đề 200, mô tả sự cố. Tôi không thể thực hiện bất kỳ thay đổi nào đối với điều này, vì vậy tôi cần phải giải quyết nó trên máy khách bằng cách nào đó.

Ví dụ: Một yêu cầu chuyển đến một số URL không được tìm thấy, vì vậy tôi nhận được Chuyển hướng 302 đến một vị trí khác. Một yêu cầu mới được gửi và tôi nhận được 200 OK, do đó ngăn lỗi gọi lại kích hoạt.

Có cách nào tôi có thể ngăn chặn yêu cầu ajax đi theo các chuyển hướng và thay vào đó gọi một lệnh gọi lại, tốt nhất là phương pháp lỗi. Ngoài ra, có thể phát hiện xem chuyển hướng đã xảy ra trong máy khách hay chưa?



8
Nó là số lẻ mà phụ trợ của bạn được báo cáo 302 cho một không tìm thấy, thay vì một 404.
Jake Feasel

Câu trả lời:


96

Tôi thấy câu hỏi của bạn thú vị, nhưng vấn đề nói chung có vẻ như tôi hiểu lầm hơn. Ít nhất tôi sẽ cố gắng giải thích sự hiểu biết của tôi về vấn đề.

Chuyển hướng im lặng (trong suốt) là một phần của XMLHttpRequestđặc điểm kỹ thuật ( đặc biệt là xem ở đây các từ "... trong suốt theo chuyển hướng ..."). Tiêu chuẩn chỉ đề cập rằng tác nhân người dùng (trình duyệt web) có thể ngăn chặn hoặc thông báo về một số loại chuyển hướng tự động, nhưng nó không phải là một phần của XMLHttpRequest. Đó là một phần của cấu hình máy khách HTTP (cấu hình hệ điều hành) hoặc cấu hình trình duyệt web. Vì vậy, jQuery.ajaxkhông thể có bất kỳ tùy chọn nào mà bạn có thể ngăn chuyển hướng.

Bạn có thể thấy rằng chuyển hướng HTTP là một phần của giao thức HTTP và không phải là một phần của XMLHttpRequest. Vì vậy, nó ở một cấp độ trừu tượng khác hoặc ngăn xếp mạng. Ví dụ: dữ liệu từ XMLHttpRequestcó thể được truy xuất từ ​​proxy HTTP hoặc từ bộ nhớ cache của trình duyệt cục bộ và đó là một phần của giao thức HTTP. Chủ yếu là máy chủ cung cấp dữ liệu chứ không phải máy khách có thể ảnh hưởng đến bộ nhớ đệm.

Bạn có thể so sánh yêu cầu từ câu hỏi của mình với yêu cầu ngăn chặn việc thay đổi địa chỉ IP của máy chủ web hoặc thay đổi đường dẫn IP trong quá trình giao tiếp. Tất cả những điều có thể thú vị trong một số trường hợp, nhưng có những phần ở cấp độ khác của ngăn xếp giao tiếp và không thể được quản lý bởi jQuery.ajaxhoặc XMLHttpRequest.

Các XMLHttpRequesttiếng nói tiêu chuẩn cấu hình khách hàng có thể có các tùy chọn mà ngăn chặn chuyển hướng. Trong trường hợp "Microsoft world", mà tôi biết rõ hơn, bạn có thể xem chức năng WinHttpSetOption có thể được sử dụng để đặt WINHTTP_OPTION_DISABLE_FEATUREtùy chọn với WINHTTP_DISABLE_REDIRECTSgiá trị. Một cách khác là việc sử dụng WINHTTP_OPTION_REDIRECT_POLICYtùy chọn với WINHTTP_OPTION_REDIRECT_POLICY_NEVERgiá trị. Một tính năng nữa mà người ta có thể sử dụng trong Windows là chức năng WinHttpSetStatusCallback có thể đặt chức năng gọi lại nhận được một số thông báo như WINHTTP_CALLBACK_FLAG_REDIRECT.

Vì vậy, có thể thực hiện các yêu cầu của bạn nói chung, nhưng giải pháp có thể sẽ không độc lập với hệ điều hành hoặc trình duyệt web và không ở cấp độ jQuery.ajaxhoặc XMLHttpRequest.


2
Câu trả lời xuất sắc với cái nhìn sâu sắc! Tôi có một số kinh nghiệm với curl, mà bạn có thể đặt các cờ tương tự như bạn đề cập. Tôi đã hy vọng rằng các hướng dẫn như vậy có thể được chuyển tới trình duyệt, nhưng từ câu trả lời của bạn, tôi hiểu rằng hành vi dự kiến ​​sẽ là thực hiện theo các chuyển hướng như thể yêu cầu ban đầu được gửi đến vị trí do máy chủ chỉ định.
Jørgen

@ Jørgen: Bạn được chào đón! Trong hầu hết các tình huống, việc chuyển hướng không phải là một vấn đề. Bạn không mô tả ngữ cảnh mà bạn sử dụng jQuery.ajax và liệu bạn có toàn quyền kiểm soát máy chủ web mà bạn gửi yêu cầu hay không. Vì vậy, thật khó để đưa ra cho bạn những lời khuyên khác thực sự có thể giải quyết vấn đề của bạn.
Oleg

Tôi không kiểm soát phía máy chủ, tôi sợ. Tôi đoán lựa chọn tốt nhất của tôi là phân tích hoặc xác thực nội dung phản hồi.
Jørgen

@ Jørgen: Tại sao chuyển hướng lại là vấn đề trong trường hợp của bạn? Nếu máy chủ di chuyển một số trang trên một vị trí khác tạm thời hoặc vĩnh viễn, nó có thể chuyển hướng yêu cầu ban đầu của bạn đến vị trí mới. Nó sẽ hoàn toàn ổn. Quản trị viên có thể định cấu hình máy chủ web để thực hiện chuyển hướng, ví dụ trong quá trình khôi phục hoạt động trên máy chủ hoặc bất kỳ công việc hỗ trợ nào khác. Nếu bạn hỏi máy chủ bằng URL có DNS, quản trị viên có thể thay đổi ánh xạ IP sang máy chủ khác. Anh ta có thể thực hiện chuyển hướng HTTP giống như cách cấu hình lại DNS. Vấn đề của bạn là gì?
Oleg

Vấn đề của tôi là chuyển hướng đi đến một trang lỗi chung. Tôi biết máy chủ nên được thiết lập theo cách khác, nhưng hiện tại tôi sẽ cần tìm giải pháp cho tình huống này.
Jørgen

23

Tôi không tin là có thể. Thư viện cơ bản (XHR) thực hiện yêu cầu mới một cách minh bạch. Điều đó đang được nói, những gì tôi đã làm trong những tình huống này (thường là loại giao dịch hết thời gian phiên đưa tôi đến trang đăng nhập) là gửi lại một tiêu đề phản hồi tùy chỉnh. Tôi cũng đã thiết lập một trình xử lý ajax chung để kiểm tra sự hiện diện của tiêu đề đó và phản hồi thích hợp khi có (ví dụ: chuyển hướng toàn bộ trang đến màn hình đăng nhập).

Trong trường hợp bạn quan tâm, đây là mã jQuery mà tôi phải xem cho tiêu đề tùy chỉnh đó:

/* redirects main window when AJAX request indicates that the session has expired on the backend. */
function checkSession(event, xhr, ajaxOptions)
{
    if (xhr.readyState == 4)
    {
        if(xhr.getResponseHeader("Login-Screen") != null && xhr.getResponseHeader("Login-Screen").length)
        {
            window.location.href='sessionExpired.html'; //whatever
        }
    }
}

$(document).ajaxComplete(checkSession)

1
Cảm ơn, tôi đoán tôi sẽ phải tìm cách tiếp cận tương tự, phân tích phản hồi.
Jørgen

11

Tôi đã tìm thấy một tính năng để kiểm tra xem cuộc gọi của bạn đã được chuyển hướng chưa. Đó là xhr.state (): nếu nó "bị từ chối" thì chuyển hướng đã xảy ra.

Ví dụ với gọi lại thành công:

request.success(function(data, textStatus, xhr)
{
    if(xhr.state() == "resolved")
    {
        //no redirection
    }
    if(xhr.state() == "rejected")
    {
        //redirection
    }
});

Ví dụ với lỗi gọi lại:

request.error(function(xhr, textStatus)
{
    if (xhr.state() == "rejected")
    {
        //redirection
        location.href = "loginpage";
    } else
    {
        //some other error happened
        alert("error");
    }
});

1
Mẹo trong câu trả lời của bạn thực sự đã giúp chúng tôi hoàn thành công việc. Vì lợi ích của các ghi chú có thể giúp ích cho những người khác, chúng tôi có Cổng thông tin WebSphere được tích hợp bảo mật với SiteMinder. Chúng tôi có một portlet cần Ajax gọi đến một url tài nguyên và khi hết thời gian, nó có các chuyển hướng minh bạch đang diễn ra nhưng chúng tôi không biết cách chuyển hướng đến trang đăng nhập. Kiểm tra jqXHR.state () bị "từ chối" chắc chắn đã giúp ích. Rất cám ơn một lần nữa.
Uresh Kuruhuri

Một kết quả tuyệt vời, tuy nhiên, có thể có kết quả dương tính giả vì trạng thái "bị từ chối" có thể được kích hoạt ngay cả khi một lời hứa bị từ chối và không chỉ khi chuyển hướng. jQuery giải thích khi nào trạng thái "bị từ chối" được gửi api.jquery.com/deferred.state
Nitin

1

Tôi không thể thêm vào trí tuệ sâu sắc của các lập trình viên trước đó đã trả lời, nhưng tôi sẽ thêm một trường hợp cụ thể mà những người khác có thể thấy hữu ích để biết.

Tôi đã xem qua chuyển hướng im lặng 302 này trong ngữ cảnh của SharePoint. Tôi có một số mã ứng dụng khách Javascript đơn giản ping một trang con SharePoint và nếu nó nhận được phản hồi 200 HTTP, nó sẽ chuyển đến trang web đó window.location. Nếu nó nhận được bất kỳ thứ gì khác, nó sẽ thông báo cho người dùng rằng trang web không tồn tại.

Tuy nhiên, trong trường hợp trang web tồn tại nhưng người dùng không có quyền, SharePoint sẽ âm thầm chuyển hướng đến trang AccessDenied.aspx. SharePoint đã thực hiện bắt tay xác thực HTTP 401 ở cấp máy chủ / trang trại - người dùng có quyền truy cập vào SharePoint. Nhưng quyền truy cập vào trang con được xử lý, tôi cho rằng sử dụng cờ cơ sở dữ liệu của một số loại. Chuyển hướng im lặng bỏ qua điều khoản "else" của tôi, vì vậy tôi không thể tự giải quyết lỗi của mình. Trong trường hợp của tôi, đây không phải là một chương trình dừng lại - đó là hành vi nhất quán có thể dự đoán được. Nhưng có một chút ngạc nhiên, và tôi đã học được vài điều về các yêu cầu HTTP trong quá trình này!


1

Tôi quan tâm đến điều tương tự và không thể tìm thấy state()phương pháp mà Takman đề cập và đã tự mày mò một chút. Vì lợi ích của mọi người lên đây để tìm kiếm câu trả lời, đây là những phát hiện của tôi:

Như đã nêu nhiều lần, bạn không thể ngăn chuyển hướng, nhưng bạn có thể phát hiện chúng. Theo MDN, bạn có thể sử dụng trong responseURLsố XMLHttpRequestObject, sẽ chứa URL cuối cùng mà phản hồi đến, sau tất cả các chuyển hướng. Lưu ý duy nhất là nó không được hỗ trợ bởi Internet Explorer (Edge có nó). Vì xhr/ jqXHRđược truyền vào hàm success/ donecủa jquery là một phần mở rộng của thực tế XMLHttpRequest, nên nó cũng sẽ có sẵn ở đó.


0

Tôi cho rằng bạn nhận được phản hồi 200 bởi vì lần thứ hai không có chuyển hướng, vì trang 404 không hết hạn, nó được lưu trong bộ nhớ cache. Điều đó có nghĩa là lần thứ hai trình duyệt cung cấp cho bạn trang trong bộ nhớ cache. Có một thuộc tính "bộ nhớ cache" trong jquery ajax. http://api.jquery.com/jQuery.ajax/

Bạn nên viết nó thành "false"


0

Mặc dù không thể tắt chuyển hướng vị trí sau trong XmlHttpRequests , nhưng khi sử dụng fetch () :

fetch('url', {redirect: manual});

Tìm nạp sẽ không cho bạn biết đâu là URL được chuyển hướng. Bạn có thể vô hiệu hóa hành vi, nhưng "redirect: manual" không nhằm mục đích cho phép người dùng xử lý chuyển hướng mà chính họ có ý định tên.
lcjury

-2

Tôi không chắc liệu điều này có áp dụng trong trường hợp của bạn hay không, nhưng bạn có thể viết mã để phản hồi các mã trạng thái cụ thể trong hàm AJAX -

$.ajax({
    url: '/admin/secret/data',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    statusCode: {
        200: function (data) {
            alert('302: Occurred');
            // Bind the JSON data to the UI
        },
        401: function (data) {
            alert('401: Occurred');
            // Handle the 401 error here.
        }
    }
});

9
Tôi không nghĩ rằng đây áp dụng vì OP cho biết ông luôn nhận được một mã trạng thái 200 do sự chuyển hướng xảy ra trong nền ..
Có Barry

-4

Trong tiêu đề yêu cầu trong trường hợp yêu cầu ajax, bạn sẽ có những điều sau

X-Requested-With    XMLHttpRequest

Theo tiêu chí này ở phía máy chủ, bạn có thể lọc các yêu cầu.


Ông muốn để kiểm tra phản ứng không phải là yêu cầu (trên đó ông đã có điều khiển)
Có Barry

Có thể Gfox đã gợi ý rằng đối với các yêu cầu ajax trả về 3xx là vô nghĩa, bạn có thể lọc loại yêu cầu này và trả về 403 chẳng hạn. khi bạn có một trang web cung cấp các trang yêu cầu xác thực biểu mẫu và các trang đó cũng thực hiện lệnh gọi ajax và bạn muốn đặt logic ủy quyền ở một nơi, thì đối với tôi đó là một câu trả lời hợp lệ.
maciejW
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.