Fiber web framework can not send ajax request - javascript

Forgive me, but I do not know English well. I use the translator deepl.com. At this point Russian programmers could not help me.
I am not a programmer, "I program only for myself". I have a problem - I can't send POST (JSON) request to server.
What I want to do - the server at Fiber which takes via POST request (JSON, XMLHttpRequest) 2 parameters from html page and after processing server gives me one string.
I use Fiber because I once made a small static site for myself, and there in the "examples" was all clear. I did a quick ctrl+C - ctrl+V, just tweaked my code. Then I tweaked the html, js, css. And I have a working site! :-)
main.go - start the server (no problems here)
package main
import (
"github.com/gofiber/fiber"
"github.com/gofiber/fiber/middleware/logger"
)
func main() {
app := fiber.New()
app.Use(logger.New())
app.Static("/", ".")
app.Get("/", func(c *fiber.Ctx) error {
return c.SendFile("./main.html")
})
app.Post("/search", PostTodo)
app.Listen(":3003")
}
search.go - logic on what to do after receiving the data. (so far just a kind of template, there is a small problem, but it mostly works).
package main
import (
"fmt"
"github.com/gofiber/fiber"
)
type Response_JSON struct {
Name string `json:"name"`
Surname string `json:"surname"`
}
func PostTodo(c *fiber.Ctx) error {
type request struct {
Name string `json:"name"`
Surname string `json:"surname"`
}
var body request
err := c.BodyParser(&body)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Cannot parse JSON",
})
}
fmt.Println("body: ", err)
todo := Response_JSON{
Name: body.Name,
Surname: body.Surname,
}
fmt.Println("todo: ", todo)
my_request := "<div>" + todo.Name + "</div>"
my_request = my_request + "<hr><div>" + todo.Surname + "</div>"
return c.SendString(my_request)
}
main.html - home page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Proba</title>
</head>
<body>
<div class="container">
<div class="logo">
<h1>Proba</h1>
</div>
<form action="/search" class="search_form" method="POST">
<div class="search">
<input type="text" id="search_name" value="" name="search_name" placeholder="Search name...">
<input type="text" id="search_surname" value="" name="search_surname" placeholder="Search surname...">
<input type="submit" id="send" class="search_button" value="Go">
</div>
</form>
<div id="result" class="result">
</div>
</div>
<script src="main.js"></script>
</body>
</html>
main.js - script processing forms after clicking (the main problem here)
let mybutton = document.getElementById("send");
mybutton.addEventListener("click", () => {
let name = document.getElementById("search_name").value;
let surname = document.getElementById("search_surname").value;
let s = {};
s.name = `${name}`;
s.surname = `${surname}`;
let search_json = JSON.stringify(s);
console.log("s: ", s);
console.log("name: ", name);
console.log("surname: ", surname);
console.log("search_json ", search_json);
let request = new XMLHttpRequest();
request.open('POST','/search');
request.setRequestHeader('Content-type', 'application/json');
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200)
document.getElementById("result").innerHTML=request.responseText;
}
request.send(search_json);
});
main2.js - a trial js that works without "click" (through it I tried to understand where the problem is)
let user = {
name: "Ivan",
surname: "Ivanov"
};
console.log("user:", user);
let json = JSON.stringify(user);
console.log("json:", json);
let request = new XMLHttpRequest();
request.open("POST", "/search");
request.setRequestHeader('Content-type', 'application/json');
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200)
document.getElementById("result").innerHTML=request.responseText;
}
request.send(json);
What I have:
1 - I start the server and go to the main.html. I fill in the data and click on the button (submit (Go)) and I see this result. The request is not sent and also strangely enough line console.log("s: ", s); did not work (output in the console did not happen).
enter image description here
enter image description here
2 - However, if you use the script main2.js, which works immediately when the page loads, then everything seems to work. The data was sent and the server processed it and returned it to me.
Although, for some reason in the file search.go output fmt.Println("body: ", err) - "nil", but in the variable "body" is decoded query body (application/json) according to the documentation.
enter image description here
enter image description here
Please help me solve the problem. I spent 2 days looking for a solution to my problem on google, yandex, youtube, but I could not find a solution to my problem.
I will be grateful to you in advance for the answer!

The issue you are seeing isn't related to Go (or even Fiber), it's because your form is being posted immediately, the javascript doesn't get a chance to fire.
You need to add preventDefault(); to stop the event "bubbling up" and triggering a form submit.
// Bind the call to the variable 'e'
mybutton.addEventListener("click", (e) => {
// Add this line!
e.preventDefault();
/* ... the rest is the same ... */

Related

send data from html field(Not Form) using AJAX to python cgi

I am trying to solve a problem, where I am suppose to send data using programmatic form which is not to use the form field itself to a backend python cgi script. However, I have no idea how to receive that text using python. With form I could use
"form = cgi.FieldStorage()". However, for now, I am trying to send the data using "XMLHttpRequest.send()" but again i don't know how to catch this data from the python cgi script. So basically in here, I am having two issues. So far, in the following code, I am trying to get input value using JS and trying to create HTTPRequest to send over to a python script. But the output results in an error which is caught in the exception "Request Failed"
#Update: I was able to fix it. If anyone ever needs it. I will keep the post.
//This is the HTML file
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Login(Async)</title>
</head>
<body>
<h1> Please Login </h1>
<label for="userName"> User Name </label><br>
<input type="text" id="username" name="username" placeholder="User"><br>
<label for="userName"> Password </label><br>
<input type="password" id="pwd" name="pwd" placeholder="Password"><br><br>
<button type="button" onclick="callCheckPass()"> Login </button>
<p id="contentArea"> </p>
</body>
<script>
function callCheckPass(){
asyncRequest = new XMLHttpRequest();
try{
asyncRequest.addEventListener("readystatechange", stateChange, false);
asyncRequest.open("POST", "checkpass.py", true);
asyncRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
asyncRequest.send("username=" + document.getElementById("username").value + "&" + "pwd="+
+ document.getElementById("pwd").value);
}catch(exception){
alert("Request Failed !!!");
}
}
function stateChange(){
if(asyncRequest.readyState == 4 && asyncRequest.status == 200){
document.getElementById("contentArea").innerHTML = asyncRequest.responseText;
}
}
</script>
</html>
//This is the python script // I am not sure how to catch HTTPRequest in python.
#!C:\Program Files\Python311\python.exe
import cgi, cgitb
cgitb.enable()
#instance of Field Storage
data = cgi.FieldStorage()
#get data from fields.
username = data.getvalue('username')
print("Content-type: text/html\r\n\r\n")
print("<html>")
print("<head><title> Test </title> </head>")
print("<body> <h1> Input: %s </h1> </body>"%(username))
print("</html>")
So basically in python program you would receive the data from asyncRequest.send() which is combination of your input field creating a query param which is essentially sent via asyncRequest.send("Query Param"); Then using the variable name used in JS you would get value within your python script.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Login(Async)</title>
</head>
<script>
function callCheckPass(){
var username = document.querySelector("#user").value;
var pwd = document.querySelector("#pass").value;
asyncRequest = new XMLHttpRequest();
asyncRequest.addEventListener("readystatechange", eve=>{
if(asyncRequest.readyState == 4){
document.getElementById("contentArea").innerHTML = asyncRequest.responseText;
}
});
asyncRequest.open("POST", "../../cgi-bin/checkpass.cgi", true);
asyncRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
asyncRequest.send("username=" + username + "&" + "pwd=" + pwd);
}
</script>
<body>
<h1> Please Login </h1>
User Name<br>
<input type="text" id="user" ><br>
Password<br>
<input type="password" id="pass" ><br><br>
<button type="button" onclick="callCheckPass()"> Login </button>
<p id="contentArea"> </p>
</body>
</html>
//Python script
#!/usr/bin/python //path to your python.exe
import cgi
import cgitb
import csv
cgitb.enable()
#instance of Field Storage
form = cgi.FieldStorage()
#get data from fields.
user = form.getvalue('username') // username -> the variable used from JS, which is essential to get value. For some reason this worked for me
pwd = form.getvalue("pwd")
print("Content-Type: text/html\n")
print("<html>")
print("<head><title> Test </title> </head>")
print("<body> <h1>")
print(form) // data printed in your web application.
print("</h1> </body>")
print("</html>")

Javascript and HTML (yes) - OpenWeatherMap API - how to search cities and get the data from them?

I'm trying to do a search engine (kind of), and am in need of help because I have some knowledge now of Javascript and HTML, but not this amount unfortunately.
This is all weather by the way, using OpenWeatherMap's free API.
Here's the HTML code:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name=""viewport" content=""width-device-width, initial-scale=1">
<title>My weather app</title>
</head>
<body>
<form>
<input type="text" id="cityName" placeholder="Enter a city name"><br>
<input type="submit" value="Get Weather Information" id="weather_data">
</form>
<div id="display_data"></div>
<h1 id=city_name"> Please wait...</h1>
<p id="myParagraph">Please wait...</p>
<img id="icon" src = "" alt = "Weather icon">
<p id="myTemp"> Please wait...</p>
<p id="minimum">Please wait...</p>
<p id="maximum">Please wait...</p>
<script src="City_Name.js"></script>
<script src="Data.js"></script>
</body>
</html>
This is the City_Name script:
// Fetch Wweather data from API and searching for a city
var weatherData = document.getElementById("weather_data");
weatherData.addEventListener('click',function(e){
e.preventDefault();
var cityName = document.getElementById("cityName").value;
var url = "https://api.openweathermap.org/data/2.5/weather?q="+cityName+"&appid={API Key}"
if(cityName == ""){
alert("Enter a city name");
}else{
fetch(url).then(function(response){
if(response.ok){
return response.json();
}else{
throw new Error(Error);
}
}).then(function(data){
console.log(data);
const html = `
<h2 class="text-danger text-center"><span class="text-dark">City:</span>${data.name}</h2>
` ;
document.getElementById("display_data").insertAdjacentHTML('afterbegin',html);
}).catch(function(error){
console.log(error);
});
}
});
And here is the Data script:
// Fetching City_Name to the script
include('City_Name.js')
// Fetch API
fetch('https://api.openweathermap.org/data/2.5/weather?q='+cityName+'&appid={API Key')
// Convert response string to json object
.then(response => response.json())
.then(response => {
// Display whole API response in browser console (take a look at it!)
console.log(response);
// Copy one element of response to our HTML paragraph
document.getElementById("myParagraph").innerHTML ="The weather is: " + response.weather[0].description;
document.getElementById("icon").src = "https://openweathermap.org/img/wn/" + response.weather[0].icon + "#2x.png";
document.getElementById("myTemp").innerHTML = "The temperature is: " + response.main.temp + " °C";
document.getElementById("minimum").innerHTML = "The minimum temperature should be: " + response.main.temp_min;
document.getElementById("maximum").innerHTML = "The minimum temperature should be: " + response.main.temp_max;
})
.catch(err => {
// Display errors in console
console.log(err);
});
The Data.js used to work fine with one city, like fetch('https://api.openweathermap.org/data/2.5/weather?q=Tokyo&appid={API Key}'), but now it doesn't.
Any help would be greatly appreciated.
Thanks!
To put it simply, you're going to need to have a single Javascript file for this to work. The City_Name.js.
After this line of code, document.getElementById("display_data").insertAdjacentHTML('afterbegin',html);, you don't need to have response.whateveritis. You're going to need data.whateveritis.
I hope that this answer will suit everyone's needs.
Thanks!
P.S.
Yes, I'm answering my own question.

XMLHttpRequest() POST returns 405 error; method not allowed

My html code:
<h2>Please finalize your details</h2>
<form id="details" method="post" class="form">
Full name: <strong name="name_1">ABCDEF</strong><br><br>
ID No:<strong name="org_number_1">123</strong><br><br>
Mobile No:<strong name="ph_number_1"">1234567890</strong><br><br>
E-mail: <strong name="email_1">ABC#DEF.COM</strong><br><br>
ID Card: <img src="profile.png" alt="preview" name="image" style="width: 100px; height: 100px;"><br><br>
<button id="go">It's correct</button>
</form>
My javascript:
document.getElementById('go').addEventListener('click', submit);
function submit(){
var nme=document.getElementsByName("name_1")[0].innerHTML;
var id=document.getElementsByName("org_number_1")[0].innerHTML;
var phone=document.getElementsByName("ph_number_1")[0].innerHTML;
var email=document.getElementsByName("email_1")[0].innerHTML;
var img=document.getElementsByName("image")[0].src;
const xhr=new XMLHttpRequest();
xhr.onload=function(){
const serverResponse=document.getElementById("response");
serverResponse.innerHTML=this.responseText;
};
xhr.open("POST", "database_registration.php");
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send("name="+nme+"&id="+id+"&phone="+phone+"&email="+email+"&img="+img); //this line throws the error "Failed to load resource: the server responded with a status of 405 (Method Not Allowed)"
}
I am executing my code in Visual Studio Code editor and my project location is in:
C:\Users\Abhishek\Desktop\Web-dev stuff\XAMPP\htdocs\Stack hack 20 20
This is the error:
Not only that, I've also tried working with Fetch API, but it throws the same error too. What do I do now? How can I make it work?
The error is not in the JS it's come from the server. What is in database_registration.php? If that doesn't have handling for POST then I'd expect the server to return 405.
404 would mean database_registration.php isn't there, but 405 means it is there, but doesn't allow POST specifically. Check the allow header on the response for the methods that are supported.
Try:
xhr.open("GET", "database_registration.php?" +
"name="+nme+"&id="+id+"&phone="+phone+"&email="+email+"&img="+img);
xhr.send();
To make a GET request instead.
Alternatively this could be an error parsing the posted content (misreported, as it should be 400 or maybe 406), try removing parts of the body to see if it works with a subset.
I have done the first checkbox (ID No) for you.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cafteria details</title>
<style>
#special{
height: 100px;
width: 100px;
border: 1px solid;
display: none;
}
</style>
</head>
<body>
<h2>Cafeteria registration</h2>
<form class="details">
Full name: <input type="text" placeholder="Please avoid any kind of prefixes" id="name" size=25><br><br>
Organization:<div id="org"><input onclick="myFunction()" type="checkbox" id="cb1">ID no: <input type="number" id="org_number"><br><br>
<input type="checkbox" id="cb2">Mobile No: <input type="tel" id="ph_number"></div><br><br>
E-mail: <input type="email" id="email" size=25><br><br>
Upload ID Card: <input type="file" name="id" accept=".pdf,.jpeg" id="img"><br><br>
</form>
<div id ="special">
</div>
<button id="button">Register</button>
</body>
<script>
function myFunction() {
var x = document.getElementById("cb1").checked;
if (x == true) {
document.getElementById("special").style.display="block";
}else{
document.getElementById("special").style.display="none";
}
}
// var x = document.getElementById("cb1").checked;
// if (x==true){
// document.getElementById("special").style.display="block";
// console.log(true)
// }
// if (document.getElementById("cb2").checked==true){
// document.getElementById("special").style.display="block";
// console.log(false)
// }
</script>
</html>
Your code looks fine. If you are using Live Server vscode extension to run your code, this is a known issue (and here) with the extension.
You could try to change the port number settings on the Live Server extension as suggested in the link above but your best bet would be to stop using Live Server to run this code.
Just start XAMPP and navigate to the right url in your browser (note you will have to eliminate spaces in your project folder name to something like stack-hack-20-20).
EDIT: It also seems to be the case with some other vscode extensions. You get a 405 status when you try to reach an endpoint. There is some restriction to using GET, HEAD or OPTIONS http methods so you either hit the endpoint using one of those methods or use a webserver like XAMPP for POST, DELETE etc.
I agree with #Keith that this error code usually indicates that the request method you used is not allowed by the server, but I've seen that not all developers use the correct error codes in every case.
I suspect you may have a parsing issue on the backend for the data you're submitting, since it isn't being URI encoded before it's sent.
Try this JavaScript instead and see if you get a different result:
document.getElementById('go').addEventListener('click', submit);
function submit() {
const formData = new FormData();
formData.append("name", document.getElementsByName("name_1")[0].innerHTML);
formData.append("id", document.getElementsByName("org_number_1")[0].innerHTML);
formData.append("phone", document.getElementsByName("ph_number_1")[0].innerHTML);
formData.append("email", document.getElementsByName("email_1")[0].innerHTML);
formData.append("img", document.getElementsByName("image")[0].src);
const xhr = new XMLHttpRequest();
xhr.onload = function() {
const serverResponse = document.getElementById("response");
serverResponse.innerHTML = this.responseText;
};
xhr.open("POST", "database_registration.php");
xhr.send(formData);
}
Try to create new url endpoint that support POST request on your backend PHP application. So your HTTP request which is sent from javascript can use POST request.

Silence net::ERR_CONNECTION_REFUSED

Connecting to a non-existent web socket server results in loud errors being logged to the console, usually to the tune of ... net::ERR_CONNECTION_REFUSED.
Anyone have an idea for a hackaround to silence this output? XMLHttpRequest won't work since it yields the same verbose error output if the server is not reachable.
The goal here is to test if the server is available, if it is then connect to it, otherwise use a fallback, and to do this without spamming the console with error output.
Chrome itself is emitting these messages, and there is no way to block them. This is a function of how chrome was built; whenever a ResourceFetcher object attempts to fetch a resource, its response is passed back to its context, and if there's an error, the browser prints it to the console - see here.
Similar question can be found here.
If you'd like, you can use a chrome console filter as this question discusses to block these errors in your console, but there is no way to programmatically block the messages.
I don't know why do you want to prevent this error output. I guess you just want to get rid of them when debugging. So I provide a work around here may be just useful for debugging.
Live demo: http://blackmiaool.com/soa/43012334/boot.html
How to use it?
Open the demo page, click the "boot" button, it will open a new tab. Click the "test" button in the new tab and check the result below. If you want to get a positive result, change the url to wss://echo.websocket.org.
Why?
By using post message, we can make browser tabs communicate with each other. So we can move those error output to a tab that we don't concern.
P.S. You can refresh the target page freely without loosing the connection between it and boot page.
P.P.S You can also use storage event to achieve this.
boot.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>boot page</title>
</head>
<body>
<button onclick="boot()">boot</button>
<p>BTW, you can boot the page without the button if you are willing to allow the "pop-up"</p>
<script>
var targetWindow;
function init() {
targetWindow
}
function boot() {
targetWindow = window.open("target.html");
}
boot();
window.addEventListener('message', function(e) {
var msg = e.data;
var {
action,
url,
origin,
} = msg;
if (action === "testUrl") {
let ws = new WebSocket(url);
ws.addEventListener("error", function() {
targetWindow.postMessage({
action: "urlResult",
url,
data: false,
}, origin);
ws.close();
});
ws.addEventListener("open", function() {
targetWindow.postMessage({
action: "urlResult",
url,
data: true,
}, origin);
ws.close();
});
}
});
</script>
</body>
</html>
target.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>target page</title>
</head>
<body>
<h4>input the url you want to test:</h4>
<textarea type="text" id="input" style="width:300px;height:100px;">
</textarea>
<br>
<div>try <span style="color:red">wss://echo.websocket.org</span> for success result(may be slow)</div>
<button onclick="test()">test</button>
<div id="output"></div>
<script>
var origin = location.origin;
var testUrl = origin.replace(/^https?/, "ws") + "/abcdef"; //not available of course
document.querySelector("#input").value = testUrl;
function output(val) {
document.querySelector("#output").textContent = val;
}
function test() {
if (window.opener) {
window.opener.postMessage({
action: "testUrl",
url: document.querySelector("#input").value,
origin,
}, origin);
} else {
alert("opener is not available");
}
}
window.addEventListener('message', function(e) {
var msg = e.data;
if (msg.action === "urlResult") {
output(`test ${msg.url} result: ${msg.data}`);
}
});
</script>
</body>
</html>

php ajax javascript/ecmascript html write to text file

I'm not overly experienced with the aforementioned technologies, but need to resolve the issues i'm experiencing with the POST function.
<!DOCTYPE html>
<html>
<head>
<title>ajax</title>
<meta charset='UTF-8'>
<script src='lib/ajaxget.js'></script>
<script src='lib/ajaxput.js'></script>
</head>
<body>
<h1>blah</h1>
<div>AJAX uploads go here.</div>
<div id="grabphpdiv"> AJAX uploads from PHP go here.</div>
<br>
<textarea id="comment" rows="5" cols="40"></textarea>
<br>
<button id="put">put</button>
<br>
<br>
<button id="get">get</button>
<script src='dyn.js'></script>
</body>
</html>
The JS 'GET' function is working, so here's the POST that doesn't work (no errors in the console) the text file doesn't update though...
function AjaxPut(URL, callback)
{ var ajaxObj = new XMLHttpRequest();
ajaxObj.open("POST", URL, true);
ajaxObj.onreadystatechange = function()
{ if (ajaxObj.status == 200)
if (ajaxObj.readyState == 4)
callback(ajaxObj.responseText);
};
ajaxObj.send("somestuff");
};
And the PHP for the post (though titled PUT here)
<?php
$jothandle = fopen("jots.txt","w");
fwrite($jothandle,$_REQUEST['line']);
Lastly, here's the JavaScript that's entitled 'dyn.js' at the bottom of the HTML. (though for brevity, i've only pasted in the POST section.
var y = document.getElementById("put");
y.addEventListener("click", runapi1);
y.addEventListener("click", grabphp1);
function runapi1()
{ AjaxPut('api/put.php', grabphp1);}
function grabphp1(response)
{ document.getElementById('grabphpdiv').innerHTML = response; }
Any help or pointers would be very much appreciated! thanks!
It looks like you aren't sending a parameter called line from your JS, but you are expecting one in your PHP code. Try sending this instead: line=somestuff e.g.
ajaxObj.send("line=somestuff");
Send POST data using XMLHttpRequest

Categories