how to make API GET call for SpotifyAPI specifically, getUserPlaylists()? - node.js

I am trying to make a web application using the Spotify web API.
I used the Spotify auth-server code provided in their GitHub repo for my authorization code https://github.com/spotify/web-api-auth-examples
I followed the instructions here https://medium.com/#jonnykalambay/now-playing-using-spotifys-awesome-api-with-react-7db8173a7b13 to create a simple app that getsCurrentPlayback and displays the songs album art of what is now playing on users Spotify account.
I added a getFeatures function to get the valence of the song.
Right now I want to call the getUsersPlaylists() function from the spotify-web-api.
Once I can get the playlists to call to work I want to iterate through the tracks in the playlist to get each tracks valence. I think once I can get the playlist API call to work I can figure out the rest on my own.
(Help a poor college student out whose teammates don't do anything and who can't get help from the Prof because of COVID)
Thanks so much in advance!
Here is the code for my App.js. I am using REACT
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Spotify from 'spotify-web-api-js';
const spotifyWebApi = new Spotify();
class App extends Component {
constructor(){
super();
const params = this.getHashParams();
this.state ={
loggedIn: params.access_token ? true : false,
nowPlaying: {
name: "Not Checked",
image: '',
trackId: "",
valence: ""
},
idParams: {
userId: ""
},
playlistParam: {
playlistName: ""
},
myAccessToken: {
token: ""
}
}
if(params.access_token){
spotifyWebApi.setAccessToken(params.access_token);
}
}
getHashParams() {
var hashParams = {};
var e, r = /([^&;=]+)=?([^&;]*)/g,
q = window.location.hash.substring(1);
while ( e = r.exec(q)) {
hashParams[e[1]] = decodeURIComponent(e[2]);
}
return hashParams;
}
getToken() {
return spotifyWebApi.getAccessToken();
}
// Get user Id of logged in account user.
async getUserId(myToken)
{
const headers = {
Authorization: `Bearer ${myToken}`
};
let userId = '';
const response = await fetch('https://api.spotify.com/v1/me/playlists',
{
headers : headers
}
);
const jsonResponse = await response.json();
if(jsonResponse)
{
userId = jsonResponse.id;
}
return userId;
}
//***HERE IS SOME CODE I HAVE TRIED***
//
// fetch("https://api.spotify.com/v1/me/playlists?limit=1&offset=0", {
// headers: {
// Accept: "application/json",
// Authorization: "Bearer",
// "Content-Type": "application/json"
// }
// })
// fetch("https://api.spotify.com/v1/me/playlists", {
// headers: {
// Authorization: "Bearer {params.access_token}"
// //console.log("Have Gotten The Playlist");
// }
// });
//
// getUserPlaylist() {
// fetch("https://api.spotify.com/v1/me/playlists/", {
// headers: {
// Authorization: "Bearer {this.getToken()}"
// }
// });
//
// console.log("Have Completed It");
//
// }
//********
getNowPlaying() {
spotifyWebApi.getMyCurrentPlaybackState()
.then((response) => {
this.setState({
nowPlaying: {
name: response.item.name,
image: response.item.album.images[0].url,
trackId: response.item.id
}
});
})
}
getFeatures(){
spotifyWebApi.getAudioFeaturesForTrack(this.state.nowPlaying.trackId)
.then(
function(data){
console.log("Valence of song: ", data.valence);
},
function(err){
console.log(err)
}
);
}
render(){
return (
<div className="App">
<a href="http://localhost:8888">
<button>Login With Spotify</button>
</a>
<div> Now Playing: { this.state.nowPlaying.name } </div>
<div>
<img src={ this.state.nowPlaying.image } style={{width: 100}}/>
</div>
<div>
Track Id: { this.state.nowPlaying.trackId } </div>
<button onClick={() => this.getNowPlaying()}>
Check Now Playing
</button>
<button onClick={() => this.getFeatures()}>
Get Valence
</button>
<button onClick={() => this.getUserPlaylist()}>
Get your Playlists
</button>
<div> Your Selected Playlist : {this.state.playlistParam.playlistName}</div>
<button onClick={() => console.log(this.getUserId(this.params.access_token))}> Get User Id</button>
</div>
);
}
}
export default App;

Related

React use axios return Axios Error {message: 'Network Error'} and TypeError: Cannot read properties of undefined (reading 'path')

when I click submit button, then web and terminal will return error like me title
but i try postman is ok , so i think is my axios setting error,how can i fixed this error? I found many similar questions, but can't not help me
the other question is , my form tag action is "/addItems", but i sending request , i got this error CANNOT POST / addItems Post http://localhost:3000/addItems 404 (Not Found)
(axios setting )
post(id, title, description, price, avatar) {
let token;
if (localStorage.getItem("user")) {
token = JSON.parse(localStorage.getItem("user")).token;
} else {
token = "";
}
const formData = new FormData();
// formData.append("id", id);
// formData.append("title", title);
// formData.append("description", description);
// formData.append("price", price);
formData.append("avatar", avatar);
return axios.post(
API_URL + "/addItems",
{ formData },
{
headers: {
Authorization: token,
"Content-Type": "multipart/form-data"
}
}
);
}
(item.route)
itemRouter.post("/addItems", upload.single("avatar"), async (req, res) => {
let { id, title, description, price, avatar } = req.body;
if (req.user.isMember()) {
return res.status(400).send("Only admin can add new items");
}
console.log(req.file);
avatar = req.file.path;
const newItem = new Item({
id,
title,
description,
price,
avatar
});
try {
await newItem.save();
console.log(req.file);
res.status(200).send("New item has been saved.");
} catch (err) {
res.status(400).send("Error");
console.log(err);
}
});
(addItemsComponent)
const handleChangePost = () => {
if (currentUser.user.role !== "admin") {
window.alert("Member can't not post item!! ");
navigate("/");
} else {
ItemService.post(avatar)
.then(() => {
window.alert("Post successfully");
navigate("/");
})
.catch((error) => {
console.log(error);
console.log(error.response);
setErrorMessage(error.response.data);
});
}
};
return (
<div>
<form action="/addItems" method="post" enctype="multipart/form-data">
<input onChange={handleChangeAvatar} value={avatar} type="file" name="avatar" />
<button type="submit" onClick={handleChangePost}>
Submit
</button>
</form>
</div>
);
Try this
return axios.post(API_URL + "/addItems", formData,
{
headers: {
Authorization: token,
"Content-Type": "multipart/form-data"
}
}
);

How to create a comment and reply section with MERN STACK

I created a comment session on my entertainment website
It’s working on backend.
It’s working on the frontend also but it’s not displaying the content the user typed on the database
This is my frontend (Comment form) logic:
export default function AddComment({ busy}) {
const [content, setContent] = useState("");
const { movieId } = useParams();
const { updateNotification } = useNotification();
const handleOnChange = ({ target }) => {
setContent(target.value);
};
const handleSubmit = async (e) => {
e.preventDefault();
const { error, message } = await addComment(movieId);
if (error) return updateNotification("error", error);
updateNotification("success", message);
const newComment = {
content,
};
setContent(newComment);
setContent("");
};
return (
<div className='p-5'>
<br />
<p className='dark:text-white text-primary'>replies</p>
<hr className='w-64' />
{/* Comment Lists */}
{/* Root Comment Form */}
{/* Form */}
<form className='flex ' onSubmit={handleSubmit} busy={busy}>
<textarea
value={content}
onChange={handleOnChange}
type='text'
autoComplete='text'
className='w-full rounded-md p-2 dark:text-white text-primary outline-none bg-transparent resize-none border-b focus:border-blue-500'
placeholder='Add New comment'
/>
<br className='dark:text-white text-primary ' />
<button
type='submit'
className=' w-5 h-14 dark:text-white text-primary bg-blue-600 hover:bg-blue-400 focus:border-blue-900 rounded-md'
>
{busy ? <ImSpinner3 className='animate-spin' /> : "Add"}
</button>
</form>
</div>
);
}
Then the addComment is coming from this API:
import { catchError, getToken } from "../utils/helper";
import client from "./client";
export const addComment = async (movieId, newComment) => {
const token = getToken();
try {
const { data } = await client.post(
`/comments/comment/${movieId}`,
newComment,
{
headers: {
authorization: "Bearer " + token,
},
}
);
return data;
} catch (error) {
return catchError(error);
}
};
The backend is working:
exports.createComment = expressAsyncHandler(async (req, res) => {
const { movieId } = req.params;
const { content } = req.body;
const userId = req.user._id;
console.log(req.body);
// verify user before comment
if (!req.user.isVerified)
return sendError(res, "Please verify your email first!");
if (!isValidObjectId(movieId)) return sendError(res, "Invalid Movie!");
// create and update new comment
const newComment = new Comment({
user: userId,
parentMovie: movieId,
content,
});
// save new comment
await newComment.save();
res.json({ message: "New comment added!!", newComment });
});
I posted with Postman on backend it gave me this on the database:
_id
:
62dcfccd93444cef55611632
user
:
62bf20d65073a7c65f549078
parentMovie
:
62c2c425465804ff32cdd06c
content
:
"hello"
createdAt
:
2022-07-24T08:03:25.666+00:00
updatedAt
:
2022-07-24T08:03:25.666+00:00
__v
:
0
on the console:
The port is listening on port 8000
connected to db
{ content: 'hello' }
POST /api/comments/comment/62c2c425465804ff32cdd06c 200 447.534 ms - 260
I posted on the frontend it gave me this on the database, no content:
_id
:
62dcfd6993444cef55611635
user
:
62bf57e8a8f3e737b2af23d9
parentMovie
:
62cc1d426785cfe42f8737a8
createdAt
:
2022-07-24T08:06:01.458+00:00
updatedAt
:
2022-07-24T08:06:01.458+00:00
__v
:
0
on the console it shows an empty object:
{}
POST /api/comments/comment/62cc1d426785cfe42f8737a8 200 364.009 ms - 242
This is how I solved the problem
Hope this solution will help many
const handleSubmit = async (e) => {
e.preventDefault();
const { error, message } = await addComment(movieId, content); // call the content and movieId from backend
if (error) return updateNotification("error", error);
updateNotification("success", message);
// push and display the content on database
const newComment = {
content,
};
setContent(newComment);
setContent("");
};
Then the API should be like this
export const addComment = async (movieId, newComment) => {
const token = getToken();
// console.log(newComment);
const body = {
content: newComment,
};
try {
const { data } = await client.post(`/comments/comment/${movieId}`, body, {
headers: {
authorization: "Bearer " + token,
},
});
return data;
} catch (error) {
return catchError(error);
}
};

3D model renderer component not loading file

I'm working on a feature for a web app I'm developing that consists in a .obj model viewer. The thing is that I don't really know how to work with the three.js library so I decided to go with a dependency to do the trick, I'm using this one. Basically what I'm doing is to get the content of the file in the redux state which is initially obtained by a backend request, so, I ultimately use the state variable and pass it a component prop to the <OBJModel /> component, but I get this error when trying to load:
https://pasteboard.co/Jtdkigq.png
https://pasteboard.co/JtdkPoRk.png
This is the front-end code:
import React from 'react';
import { OBJModel } from 'react-3d-viewer';
import { connect } from 'react-redux';
import { getModel } from './../../actions';
import golem from './../../Stone.obj';
class ModelViewer extends React.Component {
componentDidMount() {
document.querySelector('#upload-modal').style.display = 'flex';
let id = '';
let slashCounter = 0;
for (let i = 0; i < window.location.pathname.length; i++) {
if (slashCounter === 2) {
id = id + window.location.pathname[i];
}
if (window.location.pathname[i] === '/') {
slashCounter++;
}
}
this.props.getModel(id);
}
render() {
if (this.props.model.previewModel)
console.log(this.props.model.previewModel);
return (
<div style={{ display: 'flex', justifyContent: 'center' }}>
{!this.props.model.previewModel ? null : (
<OBJModel
height="500"
width="500"
position={{ x: undefined, y: -5, z: undefined }}
src={this.props.model.previewModel}
/>
)}
<div id="upload-modal" className="upload-modal">
<div className="upload-modal-content">
<p className="upload-modal-header">
<i
className="exclamation circle icon"
style={{ color: 'gray' }}
/>
Loading model...
</p>
<div
className="ui indicating progress active progress-indicator"
id="upload-bar-indicator"
>
<div className="bar" id="upload-bar">
<div className="progress" id="modal-upload-progress"></div>
</div>
</div>
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
return { model: state.model };
};
export default connect(mapStateToProps, { getModel })(ModelViewer);
This is the action function that makes the request to the backend:
export const getModel = (id) => {
return async (dispatch) => {
const config = {
onDownloadProgress: function (progressEvent) {
let percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
document.querySelector(
'#modal-upload-progress'
).innerHTML = `${percentCompleted}%`;
document.querySelector(
'#upload-bar'
).style.width = `${percentCompleted}%`;
document
.querySelector('#upload-bar-indicator')
.setAttribute('data-percent', `${percentCompleted}`);
},
};
const response = await axios.get(
`https://hushpuppys-3d-hub-api.herokuapp.com/api/v1/modelfiles/${id}.obj`,
config
);
document.querySelector('#upload-modal').style.display = 'none';
dispatch({ type: 'GET_MODEL', payload: response.data.data });
};
};
This is the controller that downloads the file from the Cloud Storage where im storing the files:
exports.fileDownloaderController = async (req, res) => {
try {
const fileName = req.params.id;
const config = {
headers: { Authorization: credentials.authorizationToken },
};
await axios
.get(
`${credentials.downloadUrl}/file/hushpuppys-3d-hub-storage/${fileName}`,
config
)
.then(function (response) {
console.log(response.data);
res.status(200).json({
status: 'success',
data: response.data,
});
})
.catch(function (err) {
console.log(err); // an error occurred
});
} catch (err) {
console.log(err);
res.status(404).json({
status: 'fail',
message: err.message,
});
}
};
And this is how the downloaded files look like when they are downloaded from the server, and logged in the console:
https://pasteboard.co/JtdpMCi.png

NodeJS PUT request returns error 400 (Bad Request)

I am trying to do a PUT request with NodeJS, Express and MongoDB. The issue that I am currently having is that I keep receiving an error **400** and I am not sure exactly why.
What I am exactly trying to do is upload edit a field in my USER collection, after a certain user has been registered. This is supposed to happen on a specific /user/edit/:id route.
My application is structured with a standard MVC pattern.
Here is how my Mongo Schema is structured:
let UserSchema = new mongoose.Schema({
username: String,
password: String,
email: String,
avatar: String,
firstName: String,
lastName: String,
laps:[{ type: Schema.Types.ObjectId, ref: 'Stats' }]
});
This is my service:
exports.updateUser = async function(user) {
let id = user.id;
let oldUser;
try {
//Find the old User Object by the Id
oldUser = await User.findById(id);
} catch(e) {
throw Error("Error occured while Finding the User");
}
// If no old User Object exists return false
if (!oldUser) {
return false;
}
//Edit the User Object
oldUser.firstName = user.firstName || oldUser.firstName;
oldUser.lastName = user.lastName || oldUser.lastName;
oldUser.avatar = user.avatar || oldUser.avatar;
try {
let savedUser = await oldUser.save();
return savedUser;
} catch(e) {
throw Error("And Error occured while updating the User");
}
};
The Controller that I am using:
exports.updateUser = async function(req, res, next) {
if (!req.body._id){
return res.status(400).json({status: 400, message: "Id must be present"})
}
let id = req.body._id;
let user = {
id,
firstName: req.body.firstName || null,
lastName: req.body.lastName || null,
avatar: req.body.avatar || null
};
try {
let updatedUser = await UserService.updateUser(user);
return res.status(200).json({status: 200, data: updatedUser, message: "Successfully Updated User"})
} catch(e) {
return res.status(400).json({status: 400, message: e.message})
}
};
Route path in router file:
router.post('/edit/:id', UserController.updateUser);
Route path for users inside server file:
app.use('/user', require('./api/routes/user.route'));
I know that most 4** errors come from the front end of the application, so I will also post my form and the constructor behind it. I am using ReactJS as a framework.
Front end Form:
class UserProfile extends Component {
constructor(props) {
super(props);
this.state = {
avatar: '',
resultsSubmitted: false
};
this.formChange = this.formChange.bind(this);
this.resultsSubmit = this.resultsSubmit.bind(this);
}
formChange(e) {
console.log("form changed" + e.target);
const { name, value } = e.target;
this.setState({ [name]: value });
}
resultsSubmit(e) {
e.preventDefault();
const accessToken = JSON.parse(localStorage.getItem('auth_user')).data.access_token;
const { avatar } = this.state;
const { dispatch } = this.props;
if (avatar) {
console.log("submitting results: " + avatar);
dispatch(userActions.addAvatar(avatar, accessToken));
}
}
render(){
const { avatar, resultsSubmitted} = this.state;
return (
<div className="container-fluid no-gutters page-login">
<div className="row">
<div className="login-wrapper">
<h2> Edit User Profile </h2>
<form onSubmit={this.resultsSubmit}>
<div className="form-group">
Paste Avatar URL: <input type="text" value={avatar} name="avatar" id="" onChange={this.formChange} />
</div>
<input type="submit" className="btn btn-primary btn-lg btn-block" value="submit"/>
</form>
</div>
</div>
</div>
)
}
}
function mapStateToProps(state) {
const { layout } = state;
return {
layout
};
}
export default connect(mapStateToProps)(UserProfile);
My dispatch:
function addAvatar(avatar, token) {
return dispatch => {
dispatch(request());
userService.addAvatar(avatar, token)
.then(
user => {
dispatch(success(user));
history.push(`${process.env.PUBLIC_URL}/`);
},
error => {
dispatch(failure(error));
dispatch(alertActions.error(error));
}
);
};
function request() { return { type: userConstants.AVATAR_REQUEST } }
function success(user) { return { type: userConstants.AVATAR_SUCCESS, user } }
function failure(error) { return { type: userConstants.AVATAR_FAILURE, error } }
}
HTTP Post service:
function addAvatar(avatar){
const requestOptions = {
method: 'POST',
headers: authHeader(),
body: avatar
};
return fetch('http://localhost:3003/user/edit/:id', requestOptions)
.then(response => {
if (!response.ok) {
console.log("+",response,"+");
return Promise.reject(response.statusText);
}else{
console.log(response, "the user service response was gooooooooooood");
}
return response.json();
})
.then(data => console.log(data,"WHT DO WE HAVE HERE?"));
}
Apologies for the huge code wall but I wanted to include all the bits.
I am getting an error 400 (Bad Request) on the route POST
http://localhost:3003/user/edit/:id
In your fetch request you are sending only avatar as a body and on your updateUser function you have the following if statement:
if (!req.body._id){
return res.status(400).json({status: 400, message: "Id must be present"})
}
so obviously you have not _id on your body request but an avatar instead, in fact you're sending your id as a param
'http://localhost:3003/user/edit/:id'
So you could change this line as a workaround
if (!req.params.id){
Hope it helps.
The below snippet shows that you are trying to get the ID parameter from the body of the request.
if (!req.body._id){
return res.status(400).json({status: 400, message: "Id must be present"})
}
Whereas, the route /user/edit/:id , shows that the ID parameter is actually passed through the URL, and to access it, all you need is to get your ID from the URL using req.params.id. req.params contains all parameters that are passed through the route or URL path.
The above snippet should be corrected to;
if (!req.params.id){
return res.status(400).json({status: 400, message: "Id must be present"})
}
Check https://expressjs.com/en/guide/routing.html#route-parameters for proper guide on how to deal with route parameter.

Trouble with sending data from react to node

I'm trying to build a website where user post queries and other users are able to answer in it. I'm trying to implement various tags in it using react-tags-input module. However i'm having problem in sending those tags to node server. Help needed.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Link } from 'react-router-dom';
import '../Login.css';
import "./Home.css";
import Post from "./Post";
import { WithContext as ReactTags } from 'react-tag-input';
const KeyCodes = {
comma: 188,
enter: 13,
};
const delimiters = [KeyCodes.comma, KeyCodes.enter];
class query extends Component {
constructor() {
super();
this.state = {
userquery:'',
queries:[],
tags: [],
suggestions: [
{ id: "Javascript", text: "Javascript" },
{ id: "Java", text: "Java" },
{ id: 'node.js', text: 'node.js' },
{ id: 'react.js', text: 'react.js' },
{ id: 'express', text: 'express' },
{ id: 'bootstrap', text: 'bootstrap' },
{ id: 'python', text: 'python' },
{ id: 'c++', text: 'c++' }
]
};
this.handleDelete = this.handleDelete.bind(this);
this.handleAddition = this.handleAddition.bind(this);
this.handleDrag = this.handleDrag.bind(this);
}
onChange = (e) => {
const state = this.state
state[e.target.name] = e.target.value;
this.setState(state);
}
componentDidMount(){
fetch('/query').
then((Response)=>Response.json()).
then(data =>{
this.setState({queries:data.reverse()});
})
}
handleDelete(i) {
const { tags } = this.state;
this.setState({
tags: tags.filter((tag, index) => index !== i),
});
}
handleAddition(tag) {
this.setState(state => ({ tags: [...state.tags, tag] }));
}
handleDrag(tag, currPos, newPos) {
const tags = [...this.state.tags];
const newTags = tags.slice();
newTags.splice(currPos, 1);
newTags.splice(newPos, 0, tag);
// re-render
this.setState({ tags: newTags });
}
render() {
const {userquery } = this.state;
const { tags, suggestions } = this.state;
return (
<div class="container">
<form action="/queries" method="POST">
<h2 class="form-signin-heading" color="blue">Want to ask something? ask here!</h2>
<label for="inputQuery" class="sr-only">query</label>
<textarea type="text" class="form-control" placeholder="want to ask something? ask here!" name="userquery" required/>
<br/>
<div class="form-group ">
<input class="form-control" type="text" name="image" placeholder="image url"/>
</div>
<div class="form-group ">
<ReactTags
name='tags'
tags={tags}
suggestions={suggestions}
handleDelete={this.handleDelete}
handleAddition={this.handleAddition}
handleDrag={this.handleDrag}
delimiters={delimiters}
/>
</div>
<br/>
<button class="btn btn-lg btn-primary btn-block" >Ask</button>
</form>
<section>
<h2> Recent Posts</h2>
</section>
{this.state.queries.map((item, key) => {
return (<Post item={item} key={key} />)
}
)
}
</div>
);
}
}
export default query;
server file - I'm able to get userquery and image but req.body.tags is returning an empty object.
app.post("/queries",isLoggedIn,function(req,res){
var postQuery =req.body.userquery;
var userImages =req.body.image;
console.log(req.body.tags);
username=req.user.username;
var newQuery = {
name:username,
image:userImages,
description:postQuery
}
Query.create(newQuery,function(err,newlyCreated){
if(err){
console.log(err);
}
else{
res.redirect("http://localhost:3000/home");
}
})
// res.send("you hit the post route")
});
Edited
onSubmit = e => {
e.preventDefault()
const {someText, tags} = this.state
const data = {someText, tags: tags.map(x => x.id)}
alert(`Submitting: ${JSON.stringify(data)}`)
fetch(
'queries',
{
method: 'POST',
mode: "cors", // no-cors, cors, *same-origin
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
credentials: "same-origin",
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
},
)
}
server.js
app.post("/queries",function(req,res){
console.log("tags are:-",req.body)
});
output
tags are:- {}
The problem is in react-tags storing selected tags as a bunch of span elements, not input. So, these values are not included in form data being submitted.
You have to handle form submit logic manually.
Here is an example of handlers you need to add/change:
onSubmit = e => {
e.preventDefault() // stop default form submission
const { field1, field2, tags } = this.state // select form input values to submit
const data = { field1, field2, tags: tags.map(t => t.id) } // create an object to submit
fetch(
'url',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
},
) // send POST request
}
onChange = e => this.setState({ [e.target.name]: e.target.value }) // for plain inputs
onAdd = tag => this.setState(state => ({ tags: [...state.tags, tag] })) // for tags input
render() {
return (
<form onSubmit={this.onSubmit}>
<input name="field1" onChange={this.onChange} />
<input name="field2" onChange={this.onChange} />
<ReactTags
tags={this.state.tags}
handleAddition={this.onAdd}
/>
<button type="submit">submit</button>
</form>
)
}
Working example is in this sandbox.
Result is here: https://prnt.sc/kg2j9p
Update: now codesandbox uses fetch and posts the form data, you can try to submit form and see outgoing request in network tab in browser dev tools.

Resources