programing

jQuery 게시 요청이 중단되었습니다.사후 매개 변수의 절반만 도착

batch 2023. 7. 30. 17:30
반응형

jQuery 게시 요청이 중단되었습니다.사후 매개 변수의 절반만 도착

LAMP 환경에서 이상한 현상을 발견했습니다.
프론트엔드에서 다음과 같은 jQuery를 사용하여 AJAX 게시 요청을 실행합니다.

$.post('save.php', {data1: d1, data2: d2, [...],  dataN: dN})

변들d1dN사전에 jQuery를 사용하여 웹 사이트(예: 텍스트 입력, 텍스트 영역, 확인란 등)에서 수집됩니다.

»save.php 매개 변수를 합니다.data1dataN한 번의 쿼리로 데이터베이스에 저장합니다.

요청 중에 페이지를 변경하지 않는 한(예: 링크 클릭) 요청은 약 500ms가 소요되며 문제 없이 작동합니다.

일반적으로 요청이 중단되고 무시될 것으로 예상하지만(이것은 문제가 되지 않습니다), (그리고 이것이 이상한 동작입니다) 요청이 완료된 것처럼 보이지만 전송된 데이터의 일부만 사용하여 저장됩니다.

이는 예를 들어 php 스크립트가 저장만 한다는 것을 의미합니다.data1data5 및세를 합니다.data6dataN비우기 위해
이 문제는 필드 이후 AJAX 요청(php 스크립트가 아님)에 의해 이미 발생한 것으로 보입니다.$_POST['data6']$_POST['dataN']이 시나리오에서는 php로 설정되지 않았습니다.

그래서 제 질문은:
이러한 현상이 발생하는 이유는 무엇입니까(예상된 동작)?
어떻게 하면 피할 수 있을까요?


문제는 jQuery도 php만의 것도 아닙니다. jQuery는 값을 정확하게 수집하여 php에 올리려고 합니다.방금 확인했습니다. 효과가 있습니다.반면에 php 스크립트는 예상대로 모든 것을 처리합니다. 단지 전체 요청을 수신하지 않습니다.
따라서 문제는 중단된 요청 자체일 것입니다.중단되거나 실패하지 않을 것으로 예상했던 것과 달리 차단될 때까지 모든 데이터를 전송합니다.
그런 다음 php는 이 게시물 데이터를 가져와서 처리하기 시작합니다 - 분명히 일부 정보가 누락되었습니다.

2 - 업데이트 2
변수 ▁a▁adding▁by▁the▁problem다▁fixed▁i니습해결을 추가하여 문제를 해결했습니다.eof나고끝 dataN그리고 그것이 php로 설정되었는지 확인합니다.이렇게 하면 모든 요청이 전송되었음을 확인할 수 있습니다.
그럼에도 불구하고 이것이 제가 여전히 이해하지 못하는 문제의 근원을 해결하지는 못합니다.
누구 도와줄 사람?

다음 작업을 수행하여 문제를 디버그합니다.

  1. 인확을 합니다.post_max_size당신의 php 설정에서 그것을 당신이 게시하고 있는 데이터 크기와 비교합니다.

  2. 사용자 HTTP 요청 작성기, 즉 사용Fiddler반환하는지 합니다.

  3. 사용하다print_r($_POST); 위에save.php당신이 그 안에서 무엇을 얻고 있는지 확인하기 위해.

  4. 다음과 같은 도구 사용Firebug무엇을 확인하기 위해jQuery가 게시되었습니다.

  5. 또한 게시하는 클라이언트 측의 json 개체를 확인해야 합니다.JSON.stringify(some_object);

  6. 인 샘플 샘 데 플 를 보 십 시 오 해 게{ "data1":1, "data2":2, "data3":3, "data4":4, "data5":5 , "data6":6 }

대부분의 경우 많은 데이터를 보내거나 데이터가 잘못되었을 수 있습니다!

편집: 매우 어리석은 행동이지만 당신도 카운트를 올렸다고 합시다. 그래서 직접 확인이 설정됩니다($_POST['data').$_POST['count'])

사이트의 할 수 합니다. 도 " 변수를 " 데몬"으로 입니다. 왜냐하면 아무도 "데이터 종료" 매개 변수를 전송하지 않기 때문입니다.HTTP POST모든 데이터가 실제로 전송되었는지 확인하도록 요청합니다.이 작업은 다음 사용자가 처리합니다.HTTP그 자체(예:HTTP 요청 본문의 끝을 탐지합니다.게다가, 저는 당신이 확인할 필요가 없다고 생각합니다.Content-Length 때 :POST데이터를 서버에 저장하는 것은 아무도 이러한 작업을 수행하지 않는다는 사실 때문입니다.하는 것처럼 .Ajax POST를 통하여jQuery).

그래서 저는 생각합니다.jQuery▁a▁sends다▁syn보냅니구를 전송합니다.POST끊겼어요.다른 페이지로 이동하여 데이터 수집을 중단하면jQuery를 구축합니다.Ajax할 수 으로 정확한 를 전송합니다.POST데이터가 차단된 상태로 서버에 저장됩니다.

당신이 사용하고 있기 때문에Firebug의 로가오시로 가 .net을 활성화합니다.persist따라서 다른 페이지로 이동할 때 트래픽 데이터가 손실되지 않습니다.그런 다음 트리거링합니다.Ajax POST페이지로 에 따라 함).Ajax)및Firebug모든 데이터를 열어 실제로 서버로 전송된 데이터POST및 확및 인▁theHeaders 이에, 탭 (그고이안에리,안에그,Request Headers

제 추측으로는 두 가지 중 하나가 발생할 수 있습니다.

  1. 되어 있는 할 수 .Firebugnet 및 탭앤더Content-Length는 의실컷(절단) 길이따정의 하게 계산됩니다.POST이라고 확신합니다. 그렇지 않으면 서버가 요청을 거부할 것입니다.Bad Request
  2. 여러 개가 있다는 것을 알게 될 것입니다.POST 이상의 요청이 했습니다.POST사용자의 다른 메커니즘에 의해 트리거된 요청(차단된 데이터 포함)Javascript즉, 당신이 생각했던 트리거가 아니라 다른 페이지로 이동함으로써 더 많은 것과 다른 것.Ajax요청이 트리거될 수 있습니다(소스 코드를 모르기 때문에 추측일 뿐).

이와 관련이 (으)로 , (으)ㄹ 수 있다, (으)ㄹ 수 있다, (으)ㄹ 수 있다, (으)ㄹ 수 있다, (으)ㄹ 수 있다, (으)ㄹ 수 있다, (으)ㄹ 수 .HTTP유효함) 구문적으로 유효함) 데이터를 클라이언트가 전송합니다.

부터, 은 당신의 터때부,당당디할수다있니습을 수 .Javascript불완전한 데이터를 서버로 보내지 않도록 하는 몇 가지 메커니즘을 구현합니다.을 모르기을 해야 알 수 데이터를 하는 과정에서 작업이 수도 . 그리고 ▁the▁again▁▁sure▁could▁that▁make▁it,▁code▁source수▁going데데있,▁to▁and어무아이다▁exactly취터어도POST모든 데이터가 실제로 수집된 경우에만 발생합니다.아니면, 아마도 당신은 다음 시간까지 내비게이션을 막을 수 있을 것입니다.Ajax요청이 완료되었거나 그런 것들이 있습니다.

만약 이 모든 것이 말이 안 된다면 흥미로운 것은 당신의 소스 코드를 더 많이 보는 것인지를 더 많이 보는 것입니다.Ajax POST다른 페이지로 이동하면 트리거되고 다른 이벤트 등이 있는 경우.당신이 보내는 샘플 데이터도 흥미로울 수 있습니다.

편집: ▁edit▁output▁data로 데이터를 출력하는 것도 지적하고 싶습니다.console.log()이 실제로 전송되는 의 소지가 있을 수도 는 단지 으로, 다▁exact▁at있▁output니▁the▁might▁givenline▁actually습▁which▁to▁a오▁log수▁evaluates▁the▁data▁it소해있's▁just,의▁is지▁being▁since▁be▁it▁mis 정확한 시간에 주어진 출력으로 평가됩니다. 이것이 실제로 전송되는 데이터라는 것은 결코 보장되지 않기 때문에, 그것은 주어진 출력에 대해 정확한 시간에 평가하는 로그 라인일 뿐입니다.console.log()이 호출됩니다.따라서 네트워크 트래픽을 스니핑하는 것이 좋습니다. 그래야 실제로 무엇이 전송되고 수신되는지 확인할 수 있기 때문입니다.그럼에도 불구하고, 이는 익숙하지 않은 경우에는 약간 까다롭지만 암호화된 트래픽을 사용하는 경우에는 불가능합니다(예: 를 사용하여HTTPS ), 그서래.Firebug net탭이 좋은 절충안이 될 수 있습니다.

확할 다니있의 할 수 .Content-LengthPHP에서 수신 인 헤더입니다.

은 POST 쿼리를 실행할 때 클라이언트 측에서 계산한 값이어야 합니다.만약 그것이 일치하지 않는다면, 그것은 바로 당신의 실수입니다.그리고 필요한 진단은 여기까지입니다. 컨텐츠 길이가 POST 데이터와 일치하지 않으면 POST를 유효하지 않은 것으로 거부합니다. 추가 매개 변수가 필요하지 않습니다. (하지만 POST 데이터 길이를 계산하는 것은 번거로울 수 있습니다.)또한 POST를 디코딩하고 길이를 확인할 수 있는 동안 PHP가 잘못된 길이를 받아들이는 것처럼 보이는 이유를 조사하고 싶을 수 있습니다(아마도 오류를 감지하는 데 필요한 정보는 다음 중 어딘가에 있을 것입니다).$_SERVER변수?).

일치하지만 여전히 데이터가 도착하지 않는 경우(즉,Content-Length더 작고, 잘라낸 POST를 올바르게 설명함), 그러면 잘라낸 후 POST가 검사되었다는 증거가 됩니다. 따라서 오류가 브라우저(또는 가능성이 낮은 jQuery)에 있거나 브라우저와 서버(프록시?) 사이에 있습니다.불완전한 쿼리(Content-Length > Actual Length)를 수신하고 있으며, 이 쿼리를 잘못 다시 작성하여 서버에 대해 즉시 거부하는 대신 "정확한" 것으로 보이게 합니다.

이론 및 해결 방법에 대한 몇 가지 테스트

요약: 전자는 틀렸지만 후자는 분명히 옳았습니다.내 테스트 시스템(Linux OpenSuSE 12.3, Apache)에서 작동하는 샘플은 아래 코드를 참조하십시오.

나는 잘못된 요청을 믿었습니다.Content-Length다음과 같이 거부될 수 있습니다.400 Bad Request.잘못했습니다.적어도 내 아파치는 훨씬 더 관대한 것 같습니다.

저는 이 간단한 PHP 코드를 사용하여 관심 있는 주요 변수에 액세스했습니다.

<?php
    $f = file_get_contents("php://input");
    print $_SERVER['CONTENT_LENGTH'];
    print "\nLen: " . strlen($f) . "\n";
?>

그리고 나서 나는 잘못된 요청을 준비했습니다.Content-Length를 사용하여 전송nc:

POST /p.php HTTP/1.0
Host: localhost
Content-Length: 666

answer=42

...그리고 보라,nc localhost 80 < request400 오류가 발생하지 않습니다.

HTTP/1.1 200 OK
Date: Fri, 14 Jun 2013 20:56:07 GMT
Server: Apache/2.2.22 (Linux/SUSE)
X-Powered-By: PHP/5.3.17
Vary: Accept-Encoding
Content-Length: 12
Content-Type: text/html

666
Len: 10

그때 저는 요청이 캐리지 리턴으로 끝나는 경우 콘텐츠 길이가 한두 개 정도 차이가 날 수 있다는 생각이 들었습니다. 그리고 어떤 캐리지 리턴 - LF? CRLF?그러나 브라우저에서 게시할 수 있도록 간단한 HTML을 추가했을 때

<form method="post" action="?"><input type="text" name="key" /><input type="submit" value="go" /></form>

XP Pro SP3에서 모두 실행되는 Firefox(최신), IE8, Chrome(최신)에서 Content-Length 값이 의 값과 동일하다는 것을 확인할 수 있었습니다.

요청이 차단된 경우를 제외하고는, 즉.

유일한 문제는php://input 에도 항상 사용할 수 있는 것은 아닙니다.POST데이터.

이것은 우리를 여전히 곤경에 빠뜨립니다.

오류가 네트워크 수준인 경우, 즉, 게시물이 준비되어 올바른 Content-Length로 제공되지만, 중단으로 인해 Horen의 이 의견이 다음을 나타내는 것처럼 보이므로 전체 데이터가 차단됩니다.

그래서 처음 두 개의 사후 매개변수만 도착했고, 때로는 매개변수의 값이 중간에 중단되기도 했습니다.

그렇다면 정말 확인하는 것.Content-LengthPHP가 불완전한 요청을 처리하는 것을 방지합니다.

<?php
    if ('POST' == $_SERVER['SERVER_PROTOCOL'])
    {
            if (!isset($_SERVER['Content-Length']))
            {
                header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', True, 400);
                die();
            }
            if (strlen(file_get_contents('php://input'))!=(int)($_SERVER['Content-Length']))
            {
                header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', True, 400);
                die();
            }
    }
    // ... go on
?>

반면에 문제가 jQuery에 있는 경우, 즉 어떤 식으로든 중단으로 인해 jQuery가 전체 게시물을 조립할 수 없지만 게시물이 구성되어 있고, 불완전한 데이터를 계산한 Content-Length가 계산되어 패킷이 전송됩니다. 그러면 해결 방법이 작동할 수 없고 "telltale" 추가 필드가 사용되어야 합니다. 또는...아마 그.postjQuery의 함수가 CRC 필드를 포함하도록 확장될 수 있습니까?

Post데이터는 다음과 같습니다.GET:

Header1: somedata1\r\n
Header2: somedata2\r\n
...
HeaderN: somedataN\r\n
\r\n
data1=1&data2=2&...&dataN=N

요청이 중단되면 경우에 따라 마지막 줄이 부분적으로만 전달될 수 있습니다.다음은 몇 가지 가능한 솔루션입니다.

  1. 비교하다Content-Length그리고.strlen($HTTP_RAW_POST_DATA)
  2. 입력 데이터 유효성 검사
  3. 한 번에 많은 데이터를 전달하지 않음

저는 트리거, 수동으로 서버 설정을 변경하고, 다른 데이터 크기를 사용하여 #$%&things에 최선을 다해 이 문제를 재현하려고 노력했지만 PHP에서 요청이 절반밖에 오지 않았습니다.단순히 Apache가 요청이 완료될 때까지 PHP를 호출하지 않기 때문입니다.PHP에서 "청크된" POST 데이터 읽기에 대한질문을 참조하십시오.

따라서 문제가 될 수 있는 유일한 방법은 Jquery가 데이터의 일부만 수집한 다음 POST 요청을 하는 것입니다.just 사용$.post('save.php', data)당신이 언급했듯이, 그런 일은 일어나지 않을 것입니다.데이터를 수집하기 위해 작동하거나 서버의 응답을 기다리는 중입니다.

모임 중에 사이트를 전환하면 요청이 없습니다.그리고 요청이 이루어진 후에 전환하고 모든 데이터가 전송되기 전에 빠르게 이동하면 아파치 서버는 이를 절반의 요청으로 보고 PHP를 호출하지 않습니다.

몇 가지 제안:

전체 요청과 부분 요청을 위해 별도의 페이지를 사용할 수 있습니까?왜냐하면 PHP는 처음 1000개의 요소만 추가하기 때문입니다.$_POST그리고 아마도 실패한 요청은 더 많은 것을 가질 것입니다.data1000=data요소들?따라서 EOF 파라미터는 없습니다.

자바스크립트의 글로벌 var에 데이터를 수집하고 있으며 데이터를 전송하는 on before unload 방법이 있을 수 있습니까?그러면 POST에 데이터가 절반밖에 없을 수 있기 때문입니다.

시드하는 데이터에 대한 정보를 공유할 수 있습니까?작은 요소(예: data1부터 data10000까지)가 많습니까, 아니면 큰 요소가 몇 개 있습니까?

항상 마지막으로 받는 것과 같은 요소입니까?말씀하신 것처럼 항상 data6처럼?만약 그렇다면, 동일한 데이터 N 필드에서 항상 실패할 가능성은 매우 희박하기 때문입니다.

제 문제는 제 게시물 중 하나에 변수가 너무 많다는 것이었습니다.PHP에는 기본적으로 1000으로 설정된 max_input_vars 변수가 있습니다.

이 행을 내 .htaccess 파일에 추가했습니다(php.ini 파일에 액세스할 수 없기 때문에).

php_value max_input_vars 5000

문제가 해결되었습니다!

호스트 로그를 확인할 수 있습니까?

/var/log/messages

지난번에 phpi에서 "누락" 게시 변수가 있었을 때, 제가 null ASCII 문자를 보내고 서버(CentOS)가 공격으로 간주하고 있다는 것을 발견하고 특정 변수를 삭제했습니다.그걸 알아내는데 일주일이나 걸렸어요!다음은 서버 로그 응답입니다.

suhosin[1173]: ALERT - ASCII-NUL chars not allowed within request variables - dropped variable 'data3' (attacker '192.168.0.37', file '/var/www/upload_reader.php')

만약 그게 당신의 문제라면, tyrto, js로 당신의 변수를 압축하고 base64로 인코딩하세요.아약스와 함께 게시한 다음 php에서 수신하고 64를 디코딩한 다음 압축을 해제합니다!그것은 나에게 해결되었습니다 ;)

서버의 php.ini 파일에서 max_input_vars를 증가시켜 문제를 해결했습니다.

배열에 1000개 이상의 변수가 있었기 때문에 일부만 서버에 수신되었습니다!

이것이 누군가에게 도움이 되기를 바랍니다!

무슨 일이 일어나고 있는지 더 자세히 알아보려면 jQuery의 agax 함수를 사용하여 agax 요청을 제대로 코딩하는 것이 어떻습니까?모든 콜백 기능을 사용하여 통화에 무슨 일이 발생했는지 또는 어떤 일이 다시 발생했는지 추적합니다.원소type는 POST 및 요소로 설정됩니다.data어떤 물체 구조든 운반할 수 있습니다.{ ... }당신이 좋아하는.

$.ajax({
    url : "save.php",
    type : "POST",
    data : {
        "ajax_call" : "SOME_CUSTOM_AJAX_REQUEST_REFERENCE",
        "data1" : data1,
        "data2" : data2,
        "data2" : data2,
        "dataN" : dataN
    },
    //dataType : "html", contentType: "text/html; charset=utf-8",
    dataType : "json", contentType: "application/json; charset=utf-8",
    beforeSend: function () {
        //alert('before send...');
    },
    dataFilter: function () {
        //alert('data filter...');
    },
    success: function(data, textStatus, jqXHR) {
        //alert('success...');
        var response = JSON.parse(jqXHR.responseText, true);
        if (undefined != response.data) {
            my_error_function();
        }
        my_response_function(response.data);
    },
    error: function(jqXHR, textStatus, errorThrown) {
        //alert('error...');            
    },
    complete: function (xhr, status) {
        //alert('end of call...');          
        my_continuation_function();
    }
});

요청을 발송하기 전에 문서에 대해 "페이지 언로드 전에" 처리기를 설정하고(다른 페이지로의 전환을 금지함) 성공 후 바인딩을 해제하십시오.

예:

$(document).on('unload', function(e){
    e.preventDefault();
    // Here you can display a message, you need to wait a bit
    return false;
});

Ubuntu/Debian 서버의 수호신 기능으로 인해 필드가 차단됩니까?

저도 같은 문제가 있어요.POST 크기는 약 650KB이며, 게시가 완료되기 전에 브라우저 창을 닫거나 Ajax의 경우 페이지를 새로 고치면 손상됩니다.agax.success()는 실행되지 않지만 부분 데이터는 200 OK 상태의 "save.php"에 게시됩니다.$_SERVER의 Content-length는 부분 데이터의 실제 Content-length와 일치하기 때문에 다른 곳에서 제안하는 것처럼 유용하지 않습니다.

이 문제를 극복하는 두 가지 방법을 알게 되었습니다.

  1. 제안하는 대로, 끝에 포스트 변수를 추가합니다.효과가 있는 것 같지만, 위험해 보입니다.
  2. save.success 스크립트를 임시 db 열에 저장한 다음 agax.success를 사용하여 데이터를 전달하지 않고 다른 php 스크립트(예: savefinal.dll)를 호출합니다. 이 스크립트는 임시 열에서 마지막 열로 데이터를 전송합니다(또는 이 데이터를 유효한 것으로 플래그만 지정합니다).이렇게 하면 게시가 중단된 경우 데이터가 데이터베이스의 임시 열에만 상주하거나 유효한 것으로 플래그가 지정되지 않습니다.

게시가 중단되면 .success()가 호출되지 않으므로 이 작업이 수행됩니다.

저는 이것이 apache에 잘못된 (매우 작은) 콘텐츠 길이를 보내는 jquery 버그라고 추측하고 apache는 게시 요청이 완료된 것으로 간주해야 하지만 저는 잘 모르겠습니다.

이러한 현상이 발생하는 이유는 무엇입니까(예상된 동작)?

또한 게시물의 일부 변수가 누락되었을 때 이 이상한 동작의 원인을 찾고 있었는데, 이 질문에서 웹 클라이언트가 다중 부품/폼 데이터로 POST 요청을 보내는 느린 연결로 매우 유사한 동작이 설명됩니다.

언급된 질문은 다음과 같습니다.

연결 속도가 느린 원격 웹 클라이언트가 멀티파트/폼 데이터 콘텐츠가 포함된 전체 POST 요청을 전송하지 못했지만 PHP가 부분적으로 수신된 데이터를 사용하여 $_POST 배열을 채우는 문제에 직면했습니다.결과적으로 $_POST 배열의 하나의 값이 불완전하고 더 많은 값이 누락될 수 있습니다.

PHP에서 불완전한 POST 요청을 확인하는 방법을 참조하십시오.

어떻게 하면 피할 수 있을까요?

여기에서 권장되는 해결책도 찾을 수 있습니다.그럼에도 불구하고, 같은 해결책은 이미 당신이 제안한 것입니다.

필드를 추가할 수 있습니다.<input type="hidden" name="complete">(예를 들어) 마지막 매개 변수로 사용합니다.PHP먼저 이 매개 변수가 클라이언트에서 전송되었는지 확인합니다. 이 매개 변수가 전송된 경우 전체 데이터를 받았는지 확인할 수 있습니다.

언급URL : https://stackoverflow.com/questions/16934226/jquery-post-request-interrupted-only-half-of-post-parameters-arrive

반응형