JSON Parse Err online men INTE lokalt (XAMPP)

Permalänk

JSON Parse Err online men INTE lokalt (XAMPP)

Jag har ett problem med JSON Parse när en JS-fil skickar fetch-anrop till en PHP-fil:

"Uncaught (in promise) SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data"

Som sagt så fungerar hela flödet offline/lokalt med XAMPP och övriga SQL+Databasanrop med PHP fungerar på min studentserver (samma studentserver tillhandahåller SQL/MariaDB online). Men när fetch-anrop görs till lokal php-fil (då lokalt på uppladad mapp på studentserver) så får jag inte tillbaka någon JSON-data i ett unikt fall som jag får tillbaka lokalt.

Detta fungerar däremot att göra mot den lokala php-filen som ska agera som en "web service":

// check if the server is working if (isset($_GET['test'])) { $response = array( 'message1' => 'Hello, world!', 'message2' => 'How are you doing today?' ); echo json_encode($response); exit(); }

Det går att testa här: http://studenter.miun.se/~maka2207/writeable/php-projekt/chat... och se korrekt JSON Parse-svar.

Här är PHP-koden i "web service"-filen (som fungerar lokalt som sagt var):

$chatData = new Chat(ConnectDB()); // Return all current chat messages for those not logged in $msgs = $chatData->getChatMsgs(); if (isset($_SESSION['username'])) { if (isset($_POST['msg'])) { $chatData->insertChatMsg($_POST['msg'], $_SESSION['username']); $chatData->updateTotalChatMsgs(); $chatData->updateTotalChatMsgsUser($_SESSION['username']); unset($_POST['msg']); $msgs = $chatData->getChatMsgs(); } echo json_encode($msgs, JSON_PRETTY_PRINT); } else { echo json_encode($msgs, JSON_PRETTY_PRINT); }

Detta är JS-koden som skriver ut mottaget JSON-svar:

// Initiate function that updates chat window function writeChat(chat) { // Empty chat window first chatbox.innerHTML = ""; // Create each chat message before output chat.forEach((chat) => { // Chat message in the form of "[DATESTAMP] username (with clickable link to profile): <message>" let msg = `<p>[${chat.chatmsg_created}] <a class="memberslink2" href="profile.php?user=${chat.chatmsg_by}">${chat.chatmsg_by}</a>: ${chat.chatmsg}</p>`; // Output to chat window chatbox.innerHTML += msg; }); } // Initiate function that retrieves chat from PHP service function updateChat() { fetch("chatnotgpt.php") .then((response) => response.json()) .then((data) => writeChat(data)); }

Och det är denna JS-funktion i samma JS-fil som genomför fetch-POST-anropet:

// Function to send message in chat window (works with BOTH Enter and mouseclick) function sendMessage(input) { // Grab current input value after stripping some tags // Show Alert and stop function if no message (after stripping tags) if (stripTags(input.value) == "") { alert("Skriv något GILTIGT först!"); return; } let getMsg = stripTags(input.value); // Prepare form let msgForm = new FormData(); msgForm.append("msg", getMsg); // Send it! fetch("chatnotgpt.php", { method: "POST", body: msgForm, }) .then((response) => response.json()) .then((data) => writeChat(data)); // Clean input box input.value = ""; }

Jag provat med chatGPT men inte kommit längre än testet ovan som visar att det går att få tillbaka någon slags JSON-data från anropad PHP-fil online. Jag har mejlat lärarna om problemet för jag misstänker att det borde vara något konfigurerat på studentserversidan om ALLA ÖVRIGA interna PHP-anrop fungerar på studentservern? Med "interna" menar jag att min SQL-server på studentservern tillhandahålls av samma studentserver.

Jag blir bara så besviken när jag såg att chattfunktionen fungerade offline och tänkte, "Coolt!" och så trillar jag på mållinjen och får inte till en supersimpel fetch-grej och jag vet inte varför.

Mvh,
WKL.

Visa signatur

<WKL:"En kodrad i taget!";/>

Permalänk
Medlem

Debugga Javascriptet i webbläsaren och se vad som kommer tillbaka från POST:en? Du blir naturligtvis tvungen att ta hand om svaret och felhantera det i stället för att bara räkna med att allt alltid beter sig som förväntat (att json() har data att arbeta på). Kontrollera minst HTTP-status-koden och Content-Type på svaret och informera användaren om det går fel, det går säkert att göra generellt om man har lite fantasi.

Vill du ha mer hjälp så får du nog visa hur request och response ser ut, till exempel genom att visa relevanta delar från nätverksfliken i browserns utvecklarläge eller genom att köra PostMan eller liknande. Känns inte troligt att någon kommer göra det åt dig, speciellt inte när du inte postat länken till användargränssnittet där Javascriptet körs.

För övrigt anser jag att lösningar som saknar hårt typade kontrakt ska förstöras.

Permalänk
Skrivet av KAD:

Debugga Javascriptet i webbläsaren och se vad som kommer tillbaka från POST:en? Du blir naturligtvis tvungen att ta hand om svaret och felhantera det i stället för att bara räkna med att allt alltid beter sig som förväntat (att json() har data att arbeta på). Kontrollera minst HTTP-status-koden och Content-Type på svaret och informera användaren om det går fel, det går säkert att göra generellt om man har lite fantasi.

Vill du ha mer hjälp så får du nog visa hur request och response ser ut, till exempel genom att visa relevanta delar från nätverksfliken i browserns utvecklarläge eller genom att köra PostMan eller liknande. Känns inte troligt att någon kommer göra det åt dig, speciellt inte när du inte postat länken till användargränssnittet där Javascriptet körs.

För övrigt anser jag att lösningar som saknar hårt typade kontrakt ska förstöras.

Tack för svaret! Jag har upptäckt att det har något med teckenkodningen i studentdatabasservern att göra med:

Studentserver-version

  • Apache/2.4.18 (Ubuntu)

  • Database client version: libmysql - mysqlnd 5.0.12-dev - 20150407 - $Id: b5c5906d452ec590732a93b051f3827e02749b83 $

  • PHP extension: mysqli Documentation

  • PHP version: 7.0.33-0ubuntu0.16.04.16

Lokal-XAMPP-version

  • Apache/2.4.54 (Win64) OpenSSL/1.1.1p PHP/8.2.0

  • Database client version: libmysql - mysqlnd 8.2.0

  • PHP extension: mysqli Documentation curl Documentation mbstring Documentation

  • PHP version: 8.2.0

Enligt chatGPT är MySQL-versionen från cirka 2015 (men inte nödvändigtvis så gammal pga. bibliotek) och PHP-versionen 8.2.0 är lite högre än PHP version 7.0.33 men jag är ingen versions-expert så jag har ingen aning om implikationerna! Jag vet bara att tidigare moment så var det stök med ÅÄÖ inuti databasen men då kunde den ändå mata in och skriva ut (trots felaktiga tecken).

Och det tror jag berodde på att "content-type" som skickades tillbaka var "text/html" medan JSON är superkänsligt och säger "fuck you" så fort den får med ett okänt tecken. Jag har inte stött på detta problem med andra fetch-anrop i tidigare kurser (Introduktion JS) där jag gjorde anrop mot Sverige Radios API.

När jag tog bort lagrade "ÅÄÖ" i databasen så visades lagrade meddelanden. Däremot så tvärvägrar den att lagra fetch-POST-anrop i student-databasservern (blir inga nya rader), medan den klarar av allt galant i lokala XAMPP-servern. Samtidigt så klarar den av att UPDATE värden i existerande rad i chatt-tabellen i student-databasservern.

De loggar jag får ut ger inget felmeddelande vad jag kan tolka:

Här körs console.log i JS:

fetch("chatnotgpt.php", { method: "POST", body: msgForm }) .then((response) => { console.log(response); return response.json();}) .then((data) => writeChat(data));

function updateChat() { fetch("chatnotgpt.php") .then((response) => { console.log(response); return response.json();}) .then((data) => writeChat(data)); }

Vad menas med "hårt typade kontrakt"? Berätta gärna vart du ser det i min kod!

Mvh,
WKL.

Visa signatur

<WKL:"En kodrad i taget!";/>

Permalänk

Jag har kommit längre: jag kan föra in data men den stenvägrar att ta med data från inmatningsfältet tillhandahållen av JS. Den kan dock inuti PHP-filen utan problem lägga in användarnamnet som skrev inlägget. Men själva inlägget lagras som tomt. Och så fort det finns ÅÄÖ i databasen där så returnerar den JSON Parse-fel.

Jag har skrivit till lärarna igen och påpekat att jag kanske behöver en uppgradering/nollställning av min student-DB. Man har endast en student-DB och kan inte skapa flera för att prova sig fram. Så är den paj måste man "nollställa" den tror jag?

Bilden visar problematiken och vilken teckenkodning som används för student-DB:n:

Det här är hela JS-koden (knappt 80 rader kod):

"use strict"; // Function for faster JS code function byId(id) { return document.getElementById(id); } // Listen for when all DOM is loaded window.addEventListener("DOMContentLoaded", () => { // Grab chat window (a <div>) and clean it first let chatbox = byId("chatBox"); chatbox.innerHTML = ""; // Initiate function that updates chat window function writeChat(chat) { // Empty chat window first chatbox.innerHTML = ""; // Create each chat message before output chat.forEach((chat) => { // Chat message in the form of "[DATESTAMP] username (with clickable link to profile): <message>" let msg = `<p>[${chat.chatmsg_created}] <a class="memberslink2" href="profile.php?user=${chat.chatmsg_by}">${chat.chatmsg_by}</a>: ${chat.chatmsg}</p>`; // Output to chat window chatbox.innerHTML += msg; }); } // Initiate function that retrieves chat from PHP service function updateChat() { fetch("chatnotgpt.php") .then((response) => response.json()) .then((data) => writeChat(data)); } // Check if input box and send button exists to start listening // and also to not get error in console if they don't exist. if (byId("sheesh") && byId("chatta")) { let input = byId("sheesh"); // = <input type="text"> field for chat msg let btn = byId("chatta"); // = <input type="submit"> submit btn but it is NOT inside <form> so no actual submit effect! // Listen for clicks on "Posta" button btn.addEventListener("click", (e) => { // Show Alert and stop function if no message (after stripping tags) if (stripTags(input.value) == "") { alert("Skriv något först!"); return; } // Use sendMessage function sendMessage(input); }); // Listen for Enter key press to also work than just click input.addEventListener("keydown", (e) => { if (e.key === "Enter") { // Show Alert and stop function if no message (after stripping tags) if (stripTags(input.value) == "") { alert("Skriv något först!"); return; } sendMessage(input); } }); // Function to send message in chat window (works with BOTH Enter and mouseclick) function sendMessage(input) { // Grab current input value after stripping some tags // Show Alert and stop function if no message (after stripping tags) if (stripTags(input.value) == "") { alert("Skriv något GILTIGT först!"); return; } let getMsg = stripTags(input.value); // Prepare form let msgForm = new FormData(); msgForm.append("msg", getMsg); console.log(msgForm); // Send it! fetch("chatnotgpt.php", { method: "POST", body: msgForm }) .then((response) => response.json()) .then((data) => writeChat(data)); // Clean input box input.value = ""; } // Function that strips all tags except <strong><i><b><u> function stripTags(str) { return str.replace(/<(?!\/?(strong|i|b|u)\b)[^>]+>/g, ""); } } // Function that updates chat every 15 seconds function updateChatEvery15seconds() { updateChat(); setTimeout(updateChatEvery15seconds, 15000); } updateChatEvery15seconds(); });

Dold text

HTML-sidan som renderas använder charset=utf-8; precis som alla andra renderade html-sidor:

<!DOCTYPE html><html lang="sv"> <head><meta charset="utf-8">...

Och detta PHP (100 rader när du räknar bort DB-boilerplate):

<?php // Include Chat + Connect classes for DB Connection // I have no clue why I must do this and cannot just include "config.php" as usual here. // Something about the fact it is not normal HTML being outputted? session_start(); header("Content-Type: application/json; utf-8;"); class Chat { // Private Class Variables for "Chat" private $mysqli; // Connected DB Connection // Function that stores received DB connection on its class instance function __construct($dbConnect) { $this->mysqli = $dbConnect; } // Function to insert new chat message public function insertChatMsg($msg, $user) { // Only allow 3 HTML tags in messages $allowed_tags = '<strong><b><i><u>'; $msg = strip_tags($msg, $allowed_tags); // SQL Injection Protection $msg = $this->mysqli->real_escape_string($msg); $user = $this->mysqli->real_escape_string($user); // Prepare SQL Query $sql = "INSERT INTO chats(chatmsg,chatmsg_total,chatmsg_by) VALUES('$msg',1,'$user');"; $result = $this->mysqli->query($sql); } // Function to retrieve current chat messages public function getChatMsgs(): array { // Grab all columns from chat $sql = "SELECT chatmsg_created,chatmsg,chatmsg_by FROM chats ORDER BY chatmsg_created DESC;"; // Query it $result = $this->mysqli->query($sql); // And return as associative array return mysqli_fetch_all($result, MYSQLI_ASSOC); } // Function to update number of total chat messages public function updateTotalChatMsgs() { $updateRow = "UPDATE chats SET chatmsg_total=chatmsg_total+1 WHERE chatmsg_by='Nostalgitrippen';"; $this->mysqli->query($updateRow); } // Function to update number of chat messages for current user public function updateTotalChatMsgsUser($username) { $updateRow = "UPDATE users SET number_of_chatposts=number_of_chatposts+1 WHERE username='$username';"; $this->mysqli->query($updateRow); } // END OF CLASS } class Connect { private $db; // Function to connect to Database by returning a mysqli-Object function __construct() { // Try connecting and store it in private $db; try { $this->db = new mysqli(DBHOST, DBUSER, DBPASS, DBDB); } // Catch error when trying to connect and output custom message catch (mysqli_sql_exception $error) { die("Sheesh! Database connection failed for some reason!"); } } public function getDB() { return $this->db; } } // Function checking if user is logged in function isLoggedIn() { // Logged in since before? if (isset($_SESSION['username'])) { return true; // Return True } else { // Otherwise Return False return false; } } // Developer Mode with local DB Connection $devmode = false; if ($devmode) { // Function for reporting errors in browsers error_reporting(-1); ini_set('display_errors', 1); // Database Variables | DEFAULT FOR XAMPP for local Database Connections define("DBHOST", "localhost"); // Address to Database hostname define("DBUSER", "root"); // Username to log into database define("DBDB", "php_projekt"); // Database name to use after login define("DBPASS", "localhost"); // Password to log into database } // If not in Developer Mode, use these public DB Connection Settings else { ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); define("DBHOST", "CENSUR"); // Address to Database hostname define("DBUSER", "CENSUR"); // Username to log into database define("DBDB", "CENSUR"); // Database name to use after login define("DBPASS", "CENSUR"); // Password to log into database } // Function to start Database connection which might // be used several times in the same PHP file function connectDB() { // Initiate Database Connection ... // Check Connect.class.php for more $connectDB = new Connect(); // Initiate DB Connection $db = $connectDB->getDB(); // Store that connection in a variable that is used by other classes' instances return $db; // Return stored connection as its return value } $chatData = new Chat(ConnectDB()); // Return all current chat messages for those not logged in $msgs = $chatData->getChatMsgs(); if (isset($_SESSION['username'])) { if (isset($_POST['msg'])) { $chatData->insertChatMsg($$_POST['msg'], $_SESSION['username']); $chatData->updateTotalChatMsgs(); $chatData->updateTotalChatMsgsUser($_SESSION['username']); unset($_POST['msg']); $msgs = $chatData->getChatMsgs(); } echo json_encode($msgs, JSON_PRETTY_PRINT); } else { echo json_encode($msgs, JSON_PRETTY_PRINT); }

Dold text

Någon får gärna kika i JS-koden och bara berätta för mig vad jag gjort där som gör att JSON Parse uppstår? Måtte det inte vara på Databassidan eller har jag gjort något magiskt med mitt fetch-anrop?

Mvh,
WKL.

Visa signatur

<WKL:"En kodrad i taget!";/>

Permalänk

Så här ser blogginläggen ut på student-DB:n men de renderas korrekt då de skickas och tolkas som "text/html":

Någon stans måste ÅÄÖ misstolkas i student-DB:n och därmed skickas ogiltiga tecken via JSON som därmed stornekas?

Mvh,
WKL.

Visa signatur

<WKL:"En kodrad i taget!";/>

Permalänk

Nu fungerar det för att jag har:

header("Content-Type: application/json; charset=iso-8859-1;");

Sedan fick jag göra så här också i PHP-filen som tar emot anrop:

if (isset($_SESSION['username'])) { if (isset($_POST['msg'])) { $msg = $_POST['msg']; $chatData->insertChatMsg(strval($msg), $_SESSION['username']);

Jag lagrar innehållet från textfältet för det är tydligen inte en "variabel i vanlig bemärkelse" enligt chatGPT utan hänvisar till ett textfält. Men jag tänker: text som text? Tydligen inte. Men det lagras och sedan kör jag strval() på den vid anrop till DB.

Det lagras så här:

Enligt chatGPT är det "iso-8559-1 som försöks tolkats som utf-8".

Slutresultatet är nice nu dock! nu vet jag hädanefter hur jag måste anpassa mig till stackars student-DB-version som inte klarar av åäöÅÄÖ. Tänk om KTH hade samma fina DB-version åt sina kodstudenter!

Helt absurdt att student-DB:n är så kinkig och jag fattar inte ens varför jag fått det att fungera. Troligen för att nu fick den åäöÅÄÖ lagrat på det vis som 2015-versionen av MySQL krävde! Jag har läst om att redan 2008 (kanske tidigare?) började SQL och PHP krångla med svenska bokstäver.

Mvh,
WKL.

Visa signatur

<WKL:"En kodrad i taget!";/>

Permalänk
Medlem

Ska nog vara nvarchar och inte varchar på kolumnerna i DBn

Permalänk
Skrivet av Ernesto:

Ska nog vara nvarchar och inte varchar på kolumnerna i DBn

Jaha, se där ja! Varken Databas-läraren eller PHP-lärarna har nämnt den lilla detaljskillnaden mellan nvarchar och varchar. Jag har inte ens hört talas om varchar, men då har jag inte läst fler än 3 kapitel i databasteknikboken så!

Jag läser här: https://stackoverflow.com/questions/144283/what-is-the-differ... att nvarchar verkar nyttja Unicode och då även kan lösa problem när DB:n interagerar med andra externa IT-relaterade system?

Vidare läser jag där att varchar tar 1 byte per tecken som "kodas" medan nvarchar tar 2 bytes och 2 bytes är vad som behövs för att kunna lagra exempel åäöÅÄÖ och liknande?

I princip skulle det behövas en kurs bara att gå igenom teckenkodning när det gäller webbutveckling, särskilt då JSON är superstrikt med felaktiga tecken. Jag kände idag att jag kanske hade behövt gå civilingenjör inom datateknik bara för att lära mig om teckenkodning, bytes, & bits innan jag ens fick börja koda lite webbkod!

Visa signatur

<WKL:"En kodrad i taget!";/>

Permalänk
Medlem
Skrivet av WebbkodsLärlingen:

Jaha, se där ja! Varken Databas-läraren eller PHP-lärarna har nämnt den lilla detaljskillnaden mellan nvarchar och varchar. Jag har inte ens hört talas om varchar, men då har jag inte läst fler än 3 kapitel i databasteknikboken så!

Jag läser här: https://stackoverflow.com/questions/144283/what-is-the-differ... att nvarchar verkar nyttja Unicode och då även kan lösa problem när DB:n interagerar med andra externa IT-relaterade system?

Vidare läser jag där att varchar tar 1 byte per tecken som "kodas" medan nvarchar tar 2 bytes och 2 bytes är vad som behövs för att kunna lagra exempel åäöÅÄÖ och liknande?

I princip skulle det behövas en kurs bara att gå igenom teckenkodning när det gäller webbutveckling, särskilt då JSON är superstrikt med felaktiga tecken. Jag kände idag att jag kanske hade behövt gå civilingenjör inom datateknik bara för att lära mig om teckenkodning, bytes, & bits innan jag ens fick börja koda lite webbkod!

Egentligen skitenkelt. Alltid UTF-8 och nvarchar, 99.99% av alla problem lösta. (Glöm i te UTC tid)