I've been trying to learn NodeJS following
this NodeJs Youtube Tutorial.
I already worked with the Fetch API for a couple of months to get data from WordPress and Google Sheets back ends.
The last videos of the Youtube playlists are about creating a To Do List app with NodeJS and the npm's express, EJS and body-parser.
However, at part 4 of the To do list app, this "teacher" is using jQuery with Ajax to POST data to NodeJS (His jQuery Code Snippet). Since I've only been working with fetch() for AJAX POST requests, i wanted to continue with this method in plain JavaScript.
My ejs file, called todo.ejs, storing the HTML Template of the page looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/assets/style.css">
<!-- Works because of express middleware.
Since we stored the public folder as a static folder,
we can request anything within that folder from the url, such as
127.0.0.1:3000/assets/styles.css
-->
<title>Todo List</title>
</head>
<body>
<h1>My Todo List</h1>
<div id="todo-table">
<form>
<input type="text" name="item" placeholder="Add new item..." required>
<button type="submit">Add Item</button>
</form>
<ul>
<% todos.forEach(todoList =>{ %>
<li> <%= todoList.item %> </li>
<% }) %>
</ul>
</div>
</body>
<script src="/assets/script.js"></script>
</html>
My script.js (linked to the todo.ejs page) looks like this:
document.addEventListener("DOMContentLoaded", function (event) {
let submitButton = document.querySelector("button");
let textField = document.querySelector("input");
submitButton.addEventListener("click", addItem);
function addItem() {
let newItem = textField.value;
let todo = {
item: newItem
};
fetch("/todo", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(todo)
}).then((res) => res.json())
.then((data) => console.log(data))
.catch((err) => console.log(err))
}
});
And my controller handling all get/post requests, called todoController.js, looks like this:
let bodyParser = require("body-parser");
let urlencodedParser = bodyParser.urlencoded({ extended: false });
// Have some items already in place
let data = [{item: "Get milk"} , {item: "Walk dog"} , {item: "Clean kitchen"}];
module.exports = function (app) {
//Handle get data requests
app.get("/todo", function (req, res) {
res.render("todo", {todos: data});
});
//Handle post data requests (add data)
app.post("/todo", urlencodedParser, function (req, res) {
console.log(req.body);
});
//Handle delete data requests
app.delete("/todo", function (req, res) {
});
};
Now, every time i populate the input field with some text and hit the enter button, my terminal outputs empty objects:
Based on those empty objects, there has to be something wrong that my POST requests are not accepted/sent correctly.
My file tree looks like this:
Anyone who maybe has (probably an obvious) answer to this?
(I know I could just grab his jQuery Ajax code snippet to make it work, but I'm eagerly trying to understand it using plain Javascript)
Thanks in advance to everyone taking time to help me :)
You need to use bodyParser.json instead of bodyParser.urlencoded.
As the names imply, urlencoded will parse url parameters while bodyParser.json will parse json in the body of the request.
I had the same problem but my express's version was > 4.5 so i used :
const express = require('express');
app = express()
app.use(express.json({
type: "*/*"
}))
instead of :
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json())
the problem was fixed by using the parameter {type : '/'} to accept all received content-types.
Related
You must GET the "candidates/2021_05/mohamed_nagy_b3b03cbe" resource from a website service:
https://hire.verkata.com/askme/
Make the GET request above appear as if you're sending it by following a link to the resource from http://google.com/candidates/mohamed_nagy using a Chrome browser running on an Android Phone. Otherwise, the web service will give you an Access Denied error.
can anyone give me some guidance on how we can do some tasks like that in android, while I didn't do so before, please?
Note: I am using pure JavaSacript fetch API but can't solve the puzzle, Unfortunately.
client index.js
let button = document.getElementById('generate');
let Info = document.querySelector('Info');
const key = 'candidates/2021_05/mohamed_nagy_b3b03cbe';
const url = 'https://hire.verkata.com/askme/';
button.addEventListener('click', () => {
fetchWeather(url, key)
.then((data) => {
postData('/', {
Information: data.content(),
})
}).then(() => {
updateUI();
})
});
const fetchWeather = async (url, key) => {
const res = await fetch(url + key)
try {
const data = await res.json();
console.log(data);
return data;
} catch (error) {
console.log("Error:", error) // appropriately handle the error
}
};
const postData = async (url = '', data = {}) => {
console.log(data)
const response = await fetch(url, {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data), // body data type must match "Content-Type" header
});
try {
const newData = await response.json();
console.log(newData);
return newData
} catch (error) {
console.log('Error', error);
}
};
const updateUI = async () => {
const request = await fetch('/all');
try {
const allData = await request.json();
console.log(allData);
document.getElementById('info').innerHTML = allData.Info;
} catch (error) {
console.log('error', error);
}
};
server.js
let projectData = {};
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
const cors = require('cors');
app.use(cors());
const fetch = require('node-fetch');
app.use(express.static('website'));
const port = 8888;
app.listen(port, () => {
console.log(`server is running on localhost port number: ${port}`)
});
app.post('/', (req, res) => {
console.log(req.body)
const newEntry = {
Info: req.body.Information,
}
projectData = newEntry // projectData.push(newEntry)
res.send(projectData)
});
app.get('/all', (req, res) => {
console.log(projectData);
res.send(projectData);
});
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fetch API</title>
<link href="https://fonts.googleapis.com/css?family=Oswald:400,600,700|Ranga:400,700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div id = "app">
<div class ="holder">
<div class="button" id="generate">Send Get Info</div>
</div>
<div class ="entry">
<div class = "title">Most Recent Entry</div>
<div id = "Holder">
<div id = "Info"></div>
</div>
</div>
</div>
<script src="app.js" type="text/javascript"></script>
</body>
</html>
the server just telling me can't get because of 404 not fount on this server
You don't need a server side code. Actually you don't need to write any code to make a GET request.
You can use API Client tools such as Postman.
The request should be in this format:
method: GET
Referer: "http://google.com/candidates/mohamed_nagy",
User-Agent: "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Mobile Safari/537.36"
(User-Agent is required to simulate a Chrome browser running on an Android Phone.)
So, you can get a response, "You need to retrieve the puzzle within 72 hours of receiving the email".
You need to use three things to solve this puzzle.
Get method
User Agent
Referrer
You can find the sample Python Code below.
import requests
url = "https://hire.verkata.com/askme/candidates/2021_05/mohamed_nagy_b3b03cbe"
""" https://www.whatismybrowser.com/guides/the-latest-user-agent/android """
headers = {'user-agent': 'Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.99 Mobile Safari/537.36',
'Referer':'http://google.com/candidates/mohamed_nagy'
}
response = requests.get(url, headers=headers)
from bs4 import BeautifulSoup
soup = BeautifulSoup(response.content, "html.parser")
print(soup.prettify())
There's a few things you can improve here and there. It seems like it's a student exercice and the subject doesn't specify the methods you should use to implement your solution, so let's go the fastest route.
You don't need server-side code
You must GET the "candidates/2021_05/mohamed_nagy_b3b03cbe" resource
from a website service: https://hire.verkata.com/askme/ Make the GET
request above appear as if you're sending it by following a link to
the resource from http://google.com/candidates/mohamed_nagy using a
Chrome browser running on an Android Phone. Otherwise, the web service
will give you an Access Denied error.
The subject doesn't say what you have to do with the data fetched to the URL https://hire.verkata.com/askme/ so I'll assume you just have to display them.
In this case, you don't need your whole server.js file. Express.js is a web framework to build all kinds of things, especially APIs and web apps, but since you don't seem to need routing nor back-end app in any way, you can just scrape it.
Acceptable HTML/JS
Again, as the subject doesn't mention anything (and since it probably won't be used in any kind of production environment), you can just put all your code in a single HTML file and it'll work just as expected.
Here's what I would do. (Keep in mind that the code below is not professional at all, and we go the fastest route, hence the acceptable in heading)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fetch API</title>
<link href="https://fonts.googleapis.com/css?family=Oswald:400,600,700|Ranga:400,700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div id="app">
<div class="holder">
<button class="button" id="call-server">Send Get Info</button>
</div>
<div class="entry">
<div class="title">Most Recent Entry</div>
<div id="holder">
<div id="display-info"></div>
</div>
</div>
</div>
</body>
<script>
let button = document.getElementById('call-server');
let info = document.getElementById('display-info');
const key = 'candidates/2021_05/mohamed_nagy_b3b03cbe';
const url = 'https://hire.verkata.com/askme/';
button.addEventListener('click', () => {
fetchWeather(`${url}${key}`)
.then((data) => {
console.log(data);
info.innerHTML = data;
}).catch((err) => {
console.error(err);
})
});
const fetchOpts = { method: 'GET',
referrer: "http://google.com/candidates/mohamed_nagy",
};
const fetchWeather = async (fullUrl) => {
try {
const res = await fetch(fullUrl, fetchOpts)
return await res.json();
} catch (error) {
console.log("Error:", error) // appropriately handle the error
}
};
</script>
</html>
I took your code and simplified it. No need for a <a> tag, that would redirect you to the link you give it in the href attribute. What they meant by
Make the GET request above appear as if you're sending it by following a link to the resource from http://google.com/candidates/mohamed_nagy
is setting the referrer header in the request. More info on this here and here.
But it still doesn't work as of the time of this answer, and here's (partially) why.
What THEIR problem is
When navigating with a browser to the full URL you gave in your post, we can see that an error pops-up directly from PHP:
Notice: Undefined index: HTTP_REFERER in /var/www/html/hire/actions/requests.php on line 34
What this error tells is that the server couldn't find the header referer in the request. As this answer states, the referer header is not guaranteed to be sent by the browser.
Unfortunately, the same error pops whether the referer header is set or not. I tried almost all the combinations of referrer and referrerPolicy and it seems it never let me access anything.
In any case, it is an uncaught error on their side and this error should never be displayed to the end user no matter what.
Conclusion
Try double-checking the URL you try to reach to see if there's any typo. If you're 100% sure of the URL, try contacting the owner or developer of https://hire.verkata.com and tell them they have an uncaught error while checking the referer header.
Try chaning this in your HTML code add this
<div class="button" id="generate">Send Get Info</div>
instead if this in the address :
<div class="button" id="generate">Send Get Info</div>
to this
<div class="button" id="generate">Send Get Info</div>
or just change the href attribute to
href="#"
I have an input field where the user enters a location, once the submit button is pressed, I can capture the data that the user entered as newLocation. However, I need to send this data to the back-end server and I am not sure how. I guess one way is to use axios.post and axios.get - but I am not quite sure how to implement that. See both front-end and back-end code below:
Front-end:
import store from "../src/store";
import axios from "axios";
const RenderButton = () => {
async function captureText() {
const locationName = document.getElementById("locationName");
let newLocation = locationName.value;
store.dispatch({ type: "locationUpdate", payload: newLocation });
}
return (
<div id="submit">
<h2>Enter Location</h2>
<input type="text" id="locationName" />
<button id="submitButton" onClick={captureText}>
Submit Location
</button>
</div>
);
};
export default RenderButton;
Back-end:
const path = require("path");
const axios = require("axios");
const app = express();
app.use("/dist", express.static(path.join(__dirname, "dist")));
app.use("/public", express.static(path.join(__dirname, "public")));
app.get("/", async (req, res, next) =>
res.sendFile(path.join(__dirname, "index.html"))
);
Axios would not be needed on the backend. You just need to set up a route in express, just like the / one that returns the html. It can take request parameters such as form data. Something like this:
app.get('/endpoint', function (req, res) {
console.log(req.body)
})
See for formdata parsing: https://stackoverflow.com/a/38763341/13357440
Also: https://expressjs.com/en/guide/routing.html
As for the frontend, many options exist that can send a request and get a response without redirecting. XMLHttpRequest (ajax) is one of the more popular ones. https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started#step_3_%E2%80%93_a_simple_example
I have a website where a user can a request for what car they want to see an article on. I'd like to save the input into a server-side file (not saved to the user's computer) so that I can see what the users want to read about.
Server code (express.js, node.js):
var express = require('express');
var app = express();
app.set('trust proxy', true)
//setting middleware
app.use(express.static('/', {index:"/seriousindex.html"})); //Serves resources from public folder
console.log(__dirname);
app.use(express.static(__dirname+"/resources/css"));
app.use(express.static(__dirname+"/resources/js"));
app.use(express.static(__dirname+"/resources/audio"));
app.use(express.static(__dirname+"/resources/visual"));
app.get('/', (req, res)=> {
res.sendFile('/seriousindex.html', {root:__dirname});
});
app.get('/*', function (req, res) {
console.log(req.originalUrl);
console.log(req.ip.split(':').pop());
res.sendFile(__dirname + req.originalUrl.replace("?", ""));
});
PORT = 9001
app.listen(PORT, () => {
console.log(`Server is listening on port: ${PORT}`);
})
Input form (HTML):
<label>
Enter a car you want to see info on here:
<form>
<input type = "form" id = "requestinput" placeholder = "Write here"></input>
<input type = "submit" method = "POST" onclick = "/submit"></input>
</form>
</label>
I'd prefer the answer to have node.js or HTML instead of php, but if the php script works I might still use it.
There is a lot of code that I copied from StackOverflow, so expect inconsistencies in my code.
Help is appreciated.
Updated! You will have to add an additional module called bodyParser, which is a middleware to help you parse incoming request bodies. Sorry I just realized it!
...express()
var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
app.post('/car', (req, res) => {
...
In your input form's element, you will need to specify attribute "action". Updated! In addition you have to add a "name" attribute to the field so that the data is tagged to a key like this e.g.{ "requestinput": "honda" }
<label>
Enter a car you want to see info on here:
<form action="/car" method="POST">
<input type ="text" name="requestinput" placeholder="Write here"></input>
<input type = "submit"></input>
<!-- This onclick is used to call a function inside the <script> of the html. In your case, the html has no function inside <script></script> so it does nothing -->
</form>
<label>
then your app will need to have a route named '/car' to receive the inputs
app.post('/car', (req, res)=>{
console.log('Data', req.body.requestinput) // changed to body
// save the data here
})
I have made basic web apps whereby data is sent via HTTP parameters. However, I am trying to send data from client-side that contains an array (a list of ingredients for a recipe) and eventually, hopefully user uploaded image (but not worried about that for now). For this I know I need to use AJAX. I have spent hours trying to get it to work but for some reason, no POST request is being sent. The user inputs are fairly basic but here's a snippet:
<label for="method"> Method </label>
<textarea id="method" name="method">method here</textarea>
</br>
<p> add ingredients </p>
<input name="ingredient" id="ingredient" placeholder="add ingredient">
<input name="quantity" id="quantity" placeholder="#"><button id="addIngBtn" type="button">Add</button><br>
<button type="submit">submit</button>
<p> Ingredients:</p>
<ul id="ingredientListUL">
I use JQUERY to allow users to append as many ingredients as they want to the list:
$(document).ready(() => {
$("#addIngBtn").click(() => {
let ingredient = $("#ingredient").val();
let quantity = $("#quantity").val();
$("#ingredient").val(""); //reset ingredient input
$("#quantity").val("");
$("ul").append(
"<li>" + ingredient + " - " + quantity + "</li>"
);
});
})
Ingredients are built into an array and then added to a new recipe object which is the data I want to send to my server:
var ingredients = [];
$("#ingredientListUL li").each((index, element) =>
ingredients.push($(element).text())
)
var recipe = {
name: $("#name").val(),
image: $("#image").val(),
oneLiner: $("#oneLiner").val(),
method: $("#method").val(),
ingredients: ingredients
}
So far so good. I presume I am doing something wrong with these next parts. Here's the AJAX post request:
$.ajax({
url: "http://localhost:5000/recipes",
type: "POST",
dataType: "json",
data: recipe,
contentType: "application/json",
complete: function () {
console.log("process complete");
},
success: function (data) {
console.log(data);
console.log("process success");
},
error: function () {
console.log(err);
}
})
And here's my server info:
// express setup
const express = require("express");
const app = express();
const port = 5000;
// set templating engine to EJS
app.set('view engine', 'ejs');
// import route files
const recipeRoutes = require("./routes/recipes")
app.use("/recipes", recipeRoutes);
// body parser
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
//--
// BASIC ROUTES
//--
app.get("/", (req, res) => res.render("landing"));
// Port
app.listen(port, () => console.log(`Server starting on port ${port}!`));
All routes, are stored in a recipe routes file, which contains the post route for this request:
// default "/" route is really "/recipes" as defined in main server file.
router.post("/", (req, res) => {
console.log(req.body.recipe);
})
The problem is that nothing appears to be sent to, or received by my server according to network tab. Even when I try to send something like:
$.post("http://localhost:5000/recipes", { test: "test" })
What am I doing wrong? Thanks.
The contentType property does not work that way. It indicates if it is URL encoded, as a multipart message, etc. Try removing it.
According to: https://api.jquery.com/jquery.ajax/ :
"If you explicitly pass in a content-type to $.ajax(), then it is
always sent to the server (even if no data is sent)"
I've found docs teaching on how to implement Twilio on server-side using Node, however, I couldn't find an end-end example where I can send a SMS coming from my client app.
Can anyone tell me what the implementation would look like to send a post custom SMS from client to server?
Disclaimer my server file is named as app.js and my client file is named as index.js
**1- This is what I have currently setup on my app.js
const express = require('express');
const app = express();
const path = require('path');
const twilio = require('twilio');
const bodyParser = require('body-parser');
//JSON DATA
const guests= require('./public/data/Guests');
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static('public'));
//SET PORT
app.set("port", process.env.PORT || 3000);
//GET JSON DATA
app.get('/data', function(req, res) {
Promise.all([guests])//combine requests into one object
.then(([guests]) => {
res.send({guests});
});
});
//CATCHALL
app.get("/*", function(req,res){
let file = req.params[0] || "/views/index.html";
res.sendFile(path.join(__dirname, "/public/", file));
});
//LISTEN ON PORT
app.listen(app.get("port"), function(){
console.log("Listening on port: " , app.get("port"));
});
let client = new twilio('xxxxxxxxxx', 'xxxxxxxxxxxxx');
app.post('/sms', (request, result) => {
const message = request.body.message;
client.messages.create({
to: +1847820802492359,
from: +8475302725792530 ,
body: message
}).then(() => {
// message sent successfully, redirect to the home page.
res.redirect('/');
}).catch((err) => {
console.error(err);
res.sendStatus(400);
});
});
-2 am trying to process a dynamic message in my index.js. The code works on the DOM properly, it is just the SMS with Twilio that isn't posting the message to the server
$(function() {
$.ajax({
type: "GET",
url: "/data",
success: res => {
//console.log(res);
handleMessage(res);
},
error: err => console.log(err)
});
//message method
let handleMessage = (res) => {
const getFirstName = res.guests.map(name => name.firstName);
//populate drop-down select
let handleSelect = () => {
//adds first names to select dropDown
$.each(getFirstName, function(i, value) {
$('#selectName').append($('<option>').text(value).attr('value', value));
});
};
handleSelect();
let handleSubmit = () => {
$("#form").submit(function(e) {
e.preventDefault();
let name = $('#selectName').val();
let greetGuest = `Welcome ${name}!`;
console.log(greetGuest);
//append to Dom
$('.showMessage').append(`<div class="newMessage"><span>${greetGuest}</span></div>`);
});
};
handleSubmit()
};
});
-3 HTML form
<form id="form" action="/sms" method="POST">
<label>
<label for=selectName>Guest
<select id="selectName" class="select " name="sms">
</select>
</label>
</label>
<input type="submit" value="send" class="btn btn-success" />
</form>
Am I having an asynchronicity issue here?
Twilio developer evangelist here.
I can give you a basic example here, which should give you a good idea of how to achieve this. I'll start with the server side, which you already have the basics of.
Firstly, I would recommend you use a POST request rather than a GET, simply because GETs can be easily repeated by users or cached by proxies. I assume you are using Express as the web application server. You will also need the body-parser module to read the data that we send from the client side.
const Twilio = require('twilio');
const express = require('express');
const bodyParser = require('body-parser');
const app = new express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static('public'));
const twilio = new Twilio(YOUR_ACCOUNT_SID, YOUR_AUTH_TOKEN);
app.post('/messages', (request, result) => {
const message = request.body.message;
twilio.messages.create({
to: TO_NUMBER,
from: FROM_NUMBER,
body: message
}).then(() => {
// message sent successfully, redirect to the home page.
res.redirect('/');
}).catch((err) => {
console.error(err);
res.sendStatus(400);
});
});
app.listen(3000);
This sets up a server which is serving static files from a public directory and then has one endpoint, POST to /messages, that sends a message.
We now need to create the client side. I shall do this in HTML only for simplicity. You need a form that will POST to the /messages endpoint with, in this case, a single field for the message. I've included a textarea to write the message in and a button to submit the form. If you save this as index.html in the public directory where you run the application from then it should work.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Send a message!</title>
</head>
<body>
<h1>Send a message!</h1>
<form action="/messages" method="POST">
<label for="message">What would you like to send?</label>
<textarea name="message" id="message"></textarea>
<button type="submit">Send!</button>
</form>
</body>
</html>
Let me know if that helps at all.
Update
So you're looking to make the request to the server using Ajax so your page doesn't reload and you can display a different message. Your current form seems to have removed the message textarea that I added, I'll put it back in again. I assume you also want to send the message to whichever guest you are welcoming at the time, but I don't know how that works in your system, so I'm going to avoid that for now and hopefully you can sort it out.
So, if you update your form to something like this:
<form id="form" action="/sms" method="POST">
<label>
<label for=selectName>Guest
<select id="selectName" class="select " name="sms">
</select>
</label>
</label>
<label for="message">Message</label>
<textarea id="message" name="message"></textarea>
<input type="submit" value="send" class="btn btn-success" />
</form>
Then you need to add to your JavaScript a way to actually submit the form (since you are preventing the submission with e.preventDefault().
const $form = $('#form');
$form.submit(function(e) {
e.preventDefault();
let name = $('#selectName').val();
let greetGuest = `Welcome ${name}!`;
console.log(greetGuest);
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: $form.serialize(),
success: function(data) {
console.log("The message has been sent");
},
error: function() {
console.error("The message couldn't be sent");
console.error(...arguments);
}
})
//append to Dom
$('.showMessage').append(
`<div class="newMessage"><span>${greetGuest}</span></div>`
);
});
In this case we are hooking into the callback for the submit event to make a new $.ajax request to the form's action, using the method (POST), and including the form data (which we get from $form.serialize()). We then setup success and error callbacks as you've done at the top of the function.
Let me know if this helps.