Link to home
Start Free TrialLog in
Avatar of dlearman1
dlearman1Flag for United States of America

asked on

Why is the .post function not connecting with server?

My recaptcha v3 code has problems that are vexing me.  In recaptcha.htm, the jQuery function:   $.post("//www.themagnolia.com/reCaptcha.php", function is not sending the data (inputName, inputEmail, etc) to the php script at recaptcha.php; although token does seem to make it through.  For some reason, the result returned appears to be the literal html code for recaptcha.php, instead of success or failure.  It would help me greatly if someone could clue me in on what's wrong. The files are attached.
reCaptcha.htm
reCaptcha.php
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

What do you see in the console when you submit?

Can you post the POST results here - specifically the PARAMETERS tab
Also let's see what is in the response tab.
Avatar of dlearman1

ASKER

I've attached a screenshot of the completed form and resulting console log. I don't think I'm getting any POST results.  I don't understand what the Parameters Tab and Response Tab is referring to.  I'm using FF Developers Edition on a MAC. I also have Chrome available.
submitted-form.pdf
console-log.pdf
When you press F12 you get the console window
One of the tabs says console
In this tab you have (in the top right) the option to turn logging on for XHR requests - make sure that is on
When a request (POST) is made it should appear in this console - if not it will be in the Network tab
Click on the request to open it (in the console - it will expand)
Click the Params tab - see image
User generated image
Julian... Thanks for the mind-opening tour of FF tools tools.

I have attached screenshots.  XHR Requests is broken into parts 1 & 2 due to screenshot limitations.

 I see a server 500 error

I changed the file permissions for reCaptcha.php to 0775 locally (via BASH terminal) and uploaded the file. My FTP Client doesn't show file permissions, but ISP says the server does show the update. I gave a quick try at running the file and so far it still showing the Internal Server Error 500.

Thanks
XHR-Requests-1.pdf
XHR-Requests-2.pdf
Network.pdf
Parameters.pdf
500 usually means a script error - whatever you are calling on the server crashed.

Is that in response to your own script that you get the 500 or Googles?
It looks like my script... not surprising!!


XHRPOST  https://www.themagnolia.com/reCaptcha.php    HTTP/1.1 500 Internal Server Error 4209ms]
Check your error log for details of what the issue could be.
I have resolved the 500 error. Post shows status = 200.

When I echo $captcha, I get a valid value. When I echo $inputName, I get an empty string. So it seems, that a value for token is received by recaptcha.php, but inputName is not. Both variables checkout prior to the Post. I don't see why one should work and not the other.
reCaptcha.htm
reCaptcha.php
Again we need to go back to the console.

When the POST is done - check the console - look at the request that was made. Open the params tab and look at what was actually sent from the browser.

Without that information we are flying blind

F12
Network Tab
Do the POST
It should appear in the list of requests
click on it to open it
Panel opens to the right with Tabs
Click Params tab - take a look at what was sent to the server

You can also right click the request to copy the parameters - see below
User generated image
Looking at the Params Tab I see the request for token to Google server. I do not see any request for recaptcha.php.
So it looks like no request was actually made, but it also seems the token was transmitted? Maybe I'm just misreading the console information.

Why do requests get labeled with GET and not POST?

Thanks for your patience.
params.pdf
Why do requests get labeled with GET and not POST?
You have different verbs that are used with a request
GET
POST
PUT
DELETE
Are the most common.
It basically defines how you exchange data with the server.
If you use a GET you pass the data in the URL example http://www.someurl.com?param=value¶m2=value2
With a POST data is sent in the body of the request.

A GET is typically used to retrieve data - you pass the parameters to the server (script) that define the resource you want and the server sends it back.
POST and PUT are for sending data to the server - to allow for unlimited data (GET has a limit of around 2k) the data is sent in the body of the request.

When you make a call to the server you decide what method you are going to use (GET / POST) - it is in the code that the choice is made.
What confuses me is that I don't believe I used GET anywhere in the transaction. Possibly, all of the listed GET requests are generated by Google's server. I don't believe my request to recaptcha.php is happening at all.
The network panel should give you a clue - the URL associated with the GET will tell you where it is going and that should tell you who initiated the call.
The GET calls were all Google initiated.

I'm still showing status 200 on my .post message but not showing any values received on reCaptcha.php end. I'm wondering if my notation on the key:value pairs. Should it be JSON ("key": "value") or Javascript (key: "value")? I think it should be  Javascript style, but I'm just looking for anything that might be wrong?

 grecaptcha.ready(function () {
            grecaptcha.execute($siteKey, {action: 'submitContactForm'}).then(function (token) {
              $('#contactForm').prepend('<input type="text" id="recaptcha_response" name="recaptcha_response" value="' + token + '">');
              $('#contactForm').prepend('<input type="text" id="action" name="action" value="submitContractForm">');

              var recaptchaResponse = document.getElementById('recaptcha_response');
              recaptchaResponse.value = token;
              console.log ("The value of token is " + token);
              console.log ("The value of inputName is " + inputName);
               
              //remove any event handlers on the form submit button
              $('#contactForm').unbind('submit').submit();

              // jQuery post form including token to php script
              $.post("./reCaptcha.php",
                { inputName: "inputName",
                  inputEmail: "inputEmail",
                  inputPhone: "inputPhone",
                  inputMessage :"inputMessage",
                  inputAddress: "inputAddress",
                  inputCity: "inputCity",
                  inputState: "inputState",
                  inputZipcode: "inputZipcode",
                  token: "token"
                }, 
              function(result) {
                console.log("The result is " + result);
                if(result.success) {
                  console.log ("You are a human");
                } else {
                  console.log ("You are a machine");
                }
              });
              console.log("The value of inputEmail is " + inputEmail);
            });
          });

Open in new window


Another thought, maybe the data is being received in reCaptcha.php, but I'm screwing up the echo statement so they are not printing?

 echo "value of inputName is $inputName <br>\r\n";   //this returns [[b]blank space[/b]]<br>
 echo "value of captcha is {$captcha}<br>\r\n";    //this returns [b]token[/b]<br>

Open in new window


Third question (sorry). Is there a way to get a carriage return + new line in php without the <br>?
We are getting ahead of ourselves.
When this runs
$.post("./reCaptcha.php",

Open in new window

It generates a POST request in the Console / Network tab of the browser.

By examining that request we can see EXACTLY what was sent to the server (the params tab)

It is pointless looking anywhere else until we have examined that POST request.

Can you post a screen shot of the POST with the PARAMS tab open and another with the RESPONSE tab open.

After that we can look at your script - where you can do a

file_put_contents('debug.log', print_r($_POST, true));

Open in new window

To see what is arriving there first.

But first point of call is the Console.
Re the JSON vs JavaScript if your script expects JSON then you need to stringify your data and add the following to your AJAX request.
'contentType: "application/json'

Open in new window


Your PHP code snippet above does not show us how you are extracting the data from the POST.
I've attached a params screenshot and my code for reCaptcha.htm & reCaptcha.php. Interesting that the params info shoes a GET request and that "no parameters for this request".

I don't know what I was looking at, but now the request does show correctly in params as POST and the request payload looks good. See attached file - params-2.pdf

It may be helpful to know that I'm trying to adapt my code from an example: https://code.tutsplus.com/tutorials/example-of-how-to-add-google-recaptcha-v3-to-a-php-form--cms-33752

I liked this tut because the author went into a much fuller explanation of the reCaptcha v3 process. The only place I diverge (knowingly) is trying to replace the cURL approach with a standard AJAX request.  I don't know cURL and not excited to get into learning another github library
params.pdf
reCaptcha.htm
reCaptcha.php
params-2.pdf
Julian,

I've modified the code. So new attachments.

Looking at the logs it seems the data is being posted to recaptcha.php. But the array $_POST isn't being created?

I'm expecting
if ($_POST) {
        $inputName = filter_input(INPUT_POST, 'inputName', FILTER_SANITIZE_STRING);
        $inputEmail = filter_input(INPUT_POST, 'inputEmail', FILTER_VALIDATE_EMAIL);
        $inputPhone = filter_input(INPUT_POST, 'inputPhone', FILTER_SANITIZE_STRING);
        $inputMessage = filter_input(INPUT_POST, 'inputMessage', FILTER_SANITIZE_STRING);
        $inputAddress = filter_input(INPUT_POST, 'inputAddress', FILTER_SANITIZE_STRING);
        $inputCity  = filter_input(INPUT_POST, 'inputCity', FILTER_SANITIZE_STRING);
        $inputState  = filter_input(INPUT_POST, 'inputState', FILTER_SANITIZE_STRING);
        $inputZipcode  = filter_input(INPUT_POST, 'inputZipcode', FILTER_SANITIZE_STRING);
        $token = filter_input(INPUT_POST, 'token', FILTER_SANITIZE_STRING);

Open in new window


to handle the data extraction
reCaptcha.htm
reCaptcha.php
XHR.tiff
response-headers.tiff
request-headers.tiff
params.tiff
payload.tiff
$.post("./reCaptcha.php",
                { inputName: "inputName",
                  inputEmail: "inputEmail",
                  inputPhone: "inputPhone",
                  inputMessage: "inputMessage",
                  inputAddress: "inputAddress",
                  inputCity: "inputCity",
                  inputState: "inputState",
                  inputZipcode: "inputZipcode",
                  token: "token"
                }, 

Open in new window


Let's first deal with the above - when you put quotes around a string it becomes a string. All the values you extracted from the form don't do anything in the above as the fields sent to the back end are just the strings shown in quotes above.

Also why are you going through such a laborious to collect the data from the form?
Why not just use the jQuery .serialize() function to do the form processing for you?
In reading up on $_POST method, I understood that the key:value pairs needed to be in JS notation, not JSON, which lead me to the quotes around the values. Is this not correct?


My basic problem is that I have very little insight into PHP and trying to learn from examples which usually don't mimic exactly what I'm trying to do.

Google isn't revealing much about the inner workings of reCaptcha v3, but this is what I believe based on reading forums, comments and code examples:

1. Google's reCaptcha library, loaded in the page head, handles preventing/delaying the default submit button action, so I don't need that functionality in my code.

2. reCaptcha v3 works by passively observing user behavior combined with user metrics from page header + other user info Google may have. It doesn't need/use form data directly at all. The only data required by Google's server is:  secret key, action and token. Online examples that passed form data must have some other purpose in mind - probably backend validation. So I don't need all that $.post data. Here is an example of the simplified code:
<?php 
	if(isset($_POST['post'])) {
		// print_r($_POST);
		$url = "https://www.google.com/recaptcha/api/siteverify";
		$data = [
			'secret' => "your_secret_key_here",
			'response' => $_POST['token'],
			// 'remoteip' => $_SERVER['REMOTE_ADDR']
		];

		$options = array(
		    'http' => array(
		      'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
		      'method'  => 'POST',
		      'content' => http_build_query($data)
		    )
		  );

		$context  = stream_context_create($options);
  		$response = file_get_contents($url, false, $context);

		$res = json_decode($response, true);
		if($res['success'] == true) {

			// Perform you logic here for ex:- save you data to database
  			echo '<div class="alert alert-success">
			  		<strong>Success!</strong> Your inquiry successfully submitted.
		 		  </div>';
		} else {
			echo '<div class="alert alert-warning">
					  <strong>Error!</strong> You are not a human.
				  </div>';
		}
	}

 ?>

Open in new window


Typically all the examples end in simple echo statements. My success code would be  if
($responseKeys["success"] == '1' && $responseKeys["action"] == $action && $responseKeys["score"] >= .5) { send the form to my formmail script, sendForm.php and display sentSuccess.htm to user} 

Open in new window


And failure would continue blocking the original submit action, and display spamBlock.htm to the user.

I'm hoping this logic appears OK to you. I will now revise my code along these lines and test it out. Hopefully, you are still willing to review my results?
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks Julian. I believe everything executes ok now.  I do have a followup question which I will post as a new question - How can I access a json object's data?
In JavaScript you parse the data using the JSON object

var json = '{"name":"Fred"}';
var person = JSON.parse(json);

Open in new window


If you are receiving JSON data as part of an AJAX request using jQuery then you can tell jQuery to parse the return for you.
$.post(url, data, function(resp) {
  // resp is parsed json
},'JSON')

Open in new window

or if you prefer the Promise approach
$.post(url, data, 'JSON')
  .then(function(resp) {
    // resp is parsed json
   })

Open in new window

or using $.ajax()
$.ajax({
  url: url,
  data: data,
  type: 'POST',
  dataType: 'JSON'
}).then(function(resp) {
    // resp is parsed json
});

Open in new window

The GET operations work in a similar fashion