skip to Main Content

I have a standard HTML input form. The issue occurs when I enter something like n in the input. I’m aware it’s a regex that means newline, but a user may for example have it in their password, and it should remain unchanged.

The behaviour I’m observing:

const value = $('#myInput').val()
console.log(value)   // Console shows: hellon (which is indeed what the user typed in)
const outputData = { password: value }
console.log(outputData)   // Console shows: { password: "hello\n"}

It would be fine if it were just a display issue, but that data is being sent to the server with the double backslash, so there is a mismatch between what the user types in and what gets sent to the server (which of course breaks things).

It’s also worth noting this doesn’t happen (everything works as expected) when I send a request body via Postman

  1. Why is this happening?
  2. How can I avoid it?

3

Answers


  1. Chosen as BEST ANSWER

    A big thanks to all of you who helped me find the answer, especially to @T.J. Crowder for walking me through the steps.

    The issue was indeed with the backslash being escaped, but it wasn't a simple display issue. Given that values with a single backslash (like hellon) inputted on the front end form were showing up on the server like hello\n, but values with a single backslash sent from Postman would show up correctly on the server like hellon (correctly), there was something happening on the client side.

    In addition, hardcoding the input on the client side with a single backslash (e.g. data: { input: "hellon" }) then sending it to the server would show up correctly with a single slash on the server, confirming it was a front-end, likely jQuery issue.

    It turns out that, when grabbing the input value, jQuery automatically escapes backslashes and special characters.

    As @Someone Special pointed out, the "right" solution here would be to prevent users from inputting backslashes and saving ourselves the headache. However - for reasons too long to go into here - users would have to input backslashes - or at least n - for this use case, so we had to handle it somehow.

    What I ended up doing: factoring in for the special characters we were expecting. We knew we had to account for n and t, so we created this function and wrapped $(input).val()s with it where necessary:

    const unescapeString = (str) => {
        return str
            .replace(/\n/g, String.fromCharCode(10))
            .replace(/\t/g, String.fromCharCode(9))
    }
    

    It's not perfect as it doesn't account for all possible cases and we'll have to update it with other special characters if the need arises for them later on, but it works for now.


  2. In JavaScript, the backslash character is used as an escape character. When you retrieve the value from an input element using $('#myInput').val(), the backslash is interpreted as an escape character.

    In your case, the user typed in "hellon", where n represents a newline character. The n sequence is a special character that represents a line break in JavaScript and many other programming languages.

    When you log the value to the console using console.log(value), the console will display the actual value, including the newline character. However, when you log the outputData object, JavaScript’s string serialization adds an extra backslash before the newline character to escape it, resulting in "hellon".

    This behavior is due to the way JavaScript handles string serialization and escaping special characters. If you were to use the outputData object in other parts of your code or send it as JSON, the extra backslash would not affect the actual value.

    If you want to remove the extra backslash from the serialized output, you can use JSON.stringify() to serialize the object explicitly:

    const outputData = { password: value };
    console.log(JSON.stringify(outputData));  // Console shows:{"password":"hellon"}
    
    Login or Signup to reply.
  3. Re the code comments in the code you shared:

    const value = $('#myInput').val()
    console.log(value)   // Console shows: hellon (which is indeed what the user typed in)
    const outputData = { password: value }
    console.log(outputData)   // Console shows: { password: "hello\n"}
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <input type="text" id="myInput" value="hellon">

    I assume you’re referring to this style of console output:

    Browser console showing hellon for the first log call, but {password: 'hello\n'} for the second

    That’s just the difference between how the Chrome console (and some others) displays the output when you pass it a string vs. when you pass it an object. JavaScript is not adding anything to the string. When you pass a string to console.log, it just shows the characters of the string (which in your case are h, e, l, l, o, , and n). But when you pass it an object, it shows you something that looks like an object literal, and since the object literal contains a string literal for password, the backslash in the string literal has to be shown escaped. (Otherwise, it would be an escape character.) But there is only one backslash in the string, not two, exactly like this:

    console.log("hello\n"); // <== Notice the escaped backslash

    The backslash is escaped in the string literal, because otherwise it wouldn’t be a backslash, it would be an escape character changing the meaning of the next character (in this case, putting a newline in the string rather than and n.) There is only one backslash in the string.

    It would be fine if it were just a display issue, but that data is being sent to the server with the double backslash…

    Two possibilities here:

    1. The extra backslash is being added by code you haven’t shown, either the code preparing the string to send to your server, or the code on the server writing it to the database. For instance, another answer posted to this question suggested doing JSON.stringify(value), but that would add an extra backslash to it for the same reason we put on in a string literal: you have to escape backslashes in JSON strings. The extra one would be removed if the server code parsed the JSON, but it wouldn’t be if the server code used the string as-is. I’m not saying you’re doing that, just that it’s the kind of thing you could be doing to see what you’re describing.

    2. OrΒ β€” with apologies! πŸ™‚Β β€” it’s possible that you’re misinterpreting what you’re seeing for what’s in the database in the same way you misinterpeting the object literal in the console and there is actually only one backslash in the database.

    Your best bet for finding out what’s causing the problem is to carefully audit the code processing the string, in particular:

    • Check the actual value of the string with a debugger just prior to sending it to the server.
    • Check how you’re encoding what you’re sending the server.
    • Check exactly what your code on the server is receiving.
    • Check what that code is doing to the string when adding the value to the database.

    Somewhere along the line, you’ll either determine there isn’t actually a problem (#2 above), or you’ll find out what’s mistakenly adding the backslash (#1 above).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search