httpServletResponse.sendRedirect – java.lang.IllegalArgumentException: Invalid characters (CR/LF) in header Location for “unicode” characters

Hello,

I am writing this post to share a problem I encountered and the solution that I used to fix it.

I make use of the httpServletResponse.sendRedirect() method quite often for one of my projects, as it allows me to reuse the same view logic for multiple URLs. Redirecting works perfectly for English characters, however it does not work properly for Unicode characters.

This is where I encountered the issue!

return "redirect:/list/blog/author/" + author + "/1";

HTTP request headers provide support for a range of characters as mentioned below.

  • Alphanumeric characters: a-z, A-Z, 0-9
  • Special characters: _ :;.,/”‘?!(){}[]@<>=-+*#$&`|~^%

The author may include both ASCII and Unicode characters, which is why the redirection method fails when Unicode characters are passed to the author variable. To avoid this issue, we should encode the characters before passing them to the redirection method.

return "redirect:/list/blog/author/" + UriUtils.encode(author, "UTF-8") + "/1";

Success! It finally works!

Related links:

Google bard: https://g.co/bard/share/7ed197a9a570

SOF: what characters are allowed in HTTP header values?

Shift-Left Monitoring Approach for Cloud Apps in Containers

It is too costly to have an inefficient code in elastic container-based environments. Shift left monitoring approach with observability solution helps.

I published my recent experience. Have a look.

Shift-Left Monitoring Approach for Cloud Apps in Containers

Execute Spring Boot command line runner in Docker container

Scope

This post will list down the steps to run a Spring Boot (or any runnable jar) in a Docker container.

O/S: Ubuntu 20 LTS

Docker version: 20.10

After the development and unit testing is completed, build the runnable jar (using Maven clean package install goals or equivalent)

Build Dockerfile

Copy the jar to a clean directory of Ubuntu host. I keep all files at /home/pandian/feedparser. FeedParser-2.jar is my jar file name.

Create a Dockerfile (in the same name, where your jar exists) using your favorite editor.

# Alpine Linux with OpenJDK JRE
FROM openjdk:8-jre-alpine
# copy JAR into image
COPY  FeedParser-2.jar /FeedParser-2.jar
# run application with this command line
CMD ["/usr/bin/java", "-jar", "-Dspring.profiles.active=default", "/FeedParser-2.jar"]

The lines starts with # are comments.

Firstly, it fetches a unix container with openjdk:8

Secondly, it copies our executable jar to / of the container

Finally, it runs our jar file

After you save and exit the editor, following is what you will see in this directory.

$ ls -alt
total 17680
drwxrwxr-x 2 pandian pandian     4096 Dec 19 03:24 .
drwxr-xr-x 8 pandian pandian     4096 Dec 19 03:20 ..
-rw-rw-r-- 1 pandian pandian      250 Dec 19 03:20 Dockerfile
-rw-r--r-- 1 pandian pandian 18091416 Dec 19 03:18 FeedParser-2.jar

Build your docker image

We need to build our image by issuing the following command

$ sudo docker build -t feedparser:latest /home/pandian/feedparser

feedparser is the image name, latest is the tag name. It will build the image by executing the commands provided in Dockerfile one by one.

$ sudo docker build -t feedparser:latest /home/pandian/feedparser
Sending build context to Docker daemon  18.09MB
Step 1/3 : FROM openjdk:8-jre-alpine
8-jre-alpine: Pulling from library/openjdk
e7c96db7181b: Pull complete
f910a506b6cb: Pull complete
b6abafe80f63: Pull complete
Digest: sha256:f362b165b870ef129cbe730f29065ff37399c0aa8bcab3e44b51c302938c9193
Status: Downloaded newer image for openjdk:8-jre-alpine
 ---> f7a292bbb70c
Step 2/3 : COPY  FeedParser-2.jar /FeedParser-2.jar
 ---> 7fb6417e9838
Step 3/3 : CMD ["/usr/bin/java", "-jar", "-Dspring.profiles.active=default", "/FeedParser-2.jar"]
 ---> Running in 44b4e9443e63
Removing intermediate container 44b4e9443e63
 ---> 23879d1fc20e
Successfully built 23879d1fc20e
Successfully tagged feedparser:latest

If you list the images, you will see a new image by name feedparser got added.

$ sudo docker images
REPOSITORY    TAG            IMAGE ID       CREATED         SIZE
feedparser    latest         23879d1fc20e   2 minutes ago   103MB
hello-world   latest         feb5d9fea6a5   2 months ago    13.3kB
openjdk       8-jre-alpine   f7a292bbb70c   2 years ago     84.9MB

Run the container

Last step is to run the container. Issue the following command.

$ sudo docker run feedparser

This command will kick start the application in a container.

$ sudo docker run feedparser
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/FeedParser-2.jar!/BOOT-INF/lib/logback-classic-1.2.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/FeedParser-2.jar!/BOOT-INF/lib/slf4j-simple-1.7.32.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
19:31:10.253 [main] INFO org.grassfield.feed.parser.FeedParserApplication - Starting FeedParser

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.1)

19:31:11.508 [main] INFO  o.g.f.parser.FeedParserApplication:55 - Starting FeedParserApplication v2 using Java 1.8.0_212 on 867ffa00ea49 with PID 1 (/FeedParser-2.jar started by root in /)

Powershell: Cannot overwrite variable Host because it is read-only or constant

I got the following error while executing my powershell script.

Cannot overwrite variable host because it is read-only or constant.
At line:1 char:1

  • ~~~~~~~~~~~~~~~~~
    • CategoryInfo : WriteError: (host:String) [], SessionStateUnauthorizedAccessException
    • FullyQualifiedErrorId : VariableNotWritable

$host is a reserved word in powershell. So it worked after replacing $host with $hostname

phpMyAdmin – Error Incorrect format parameter

I got this error while importing a 150MB database to MariaDb/MySQL from phpMyAdmin.

phpMyAdmin – Error

Incorrect format parameter

This is a generic error. We may not understand in first shot. This was related to the upload limits specified in php.ini used by Apache. the upload max file size was set at 2 MB and post max size was set at 8 MB by default. My database is above this. So I changed the following parameters in php.ini.

sudo vi /etc/php/7.4/apache2/php.ini

Find the replace the values for the following parameters

upload_max_filesize=200M
post_max_size=200M

Restart apache service.

sudo service apache2 restart

The error will be resolved by now.

phpMyAdmin: Login without a password is forbidden by configuration (see AllowNoPassword)

Development environments will not have a root password, generally. But phpMyAdmin has a setting that discourages password-less login. If you do so, you will get the below error.

Login without a password is forbidden by configuration (see AllowNoPassword)

If you still want to setup the password-less login, some people suggests following option. But it didn’t work for me.

phpMyAdmin Config Change

Edit config.inc.php. (Ensure you have a backup before you do so. Otherwise, you may corrupt the whole config file.)

$ sudo vi /etc/phpmyadmin/config.inc.php

You will find a line like this

// $cfg['Servers'][$i]['AllowNoPassword'] = TRUE;

Uncomment this.

Still some of them say it works for their version and Operating system.

Creating a super user for phpMyAdmin

MySQL does not allow root user to login from phpMyAdmin. So you may create a super user for phpmyadmin using the following queries.

CREATE USER 'pmauser'@'localhost' IDENTIFIED WITH mysql_native_password BY '<your password>';
GRANT ALL PRIVILEGES ON . TO 'pmauser'@'localhost' WITH GRANT OPTION;
flush privileges

Feed in the username and password to phpMyAdmin. It worked for me.

ERROR 1698 (28000): Access denied for user ‘root’@’localhost’

This is the error I got while logging in as root user to MySQL database for the very first time.

ERROR 1698 (28000): Access denied for user ‘root’@’localhost’

I didn’t do anything wrong while logging in.

$ mysql -u root -p
Enter password: 
ERROR 1698 (28000): Access denied for user 'root'@'localhost'

Ubuntu uses Unix authorisation socket plugin, which will consider the unix user from which you launch mysql client. So I need to jump in as root to execute mysql client as shown below.

$ sudo mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.26-0ubuntu0.20.04.3 (Ubuntu)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

https://dev.mysql.com/doc/mysql-security-excerpt/8.0/en/socket-pluggable-authentication.html

Avoiding null variables while serializing with Jackson

I perform some CRUD operation by consuming REST APIs. Some of the entities I want to create do not have values for non-mandatory fields. When I pass those entities to servers, the call breaks with a NullPointerException. Hence I do not want to send a variable if it is null. We shall use JsonInclude annotation as shown below

@JsonInclude(JsonInclude.Include.NON_NULL)
String to;

Ansible: Missing sudo password

So here is the another error while getting the uname of the remote boxes

$ ansible webservers -b --become-user=myuser -m shell -a 'uname -a' -u myuser
192.168.1.139 | FAILED | rc=-1 >>
Missing sudo password

After executing it with explicit become password it worked.

$ ansible webservers -b --become-user=myuser -m shell -a 'uname -a' -u myuser --extra-vars "ansible_sudo_pass=mypassword"