Spring's URIComponentsBuilder converts colon (:) for port number into slash (/) - spring-web

In a test, I am injecting an example URL with a colon for a port number ("http://example.com:port") into my configuration, which is then used by my production code to construct a UriComponentsBuilder which ultimately creates a URI String.
However, that colon character is being converted into a forward slash by the UriComponentsBuilder, as demonstrated in this MCVE:
#Test
public void portNumberFromHttpUrl() {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com:port");
String uriString = builder.toUriString();
assertThat(uriString).isEqualTo("http://example.com:port");
}
This test fails as follows:
org.junit.ComparisonFailure:
Expected :"http://example.com:port"
Actual :"http://example.com/port"
Why is the : being converted to a /?

The MCVE helped me answer this myself almost immediately, but I'll leave the question here because I couldn't find the same question here or anywhere else online, and I guess it might save someone else some time:
It seems that UriComponentsBuilder recognises that a port should be a number, so this (more realistic) case passes:
#Test
public void portNumberFromHttpUrl() {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com:123");
String uriString = builder.toUriString();
assertThat(uriString).isEqualTo("http://example.com:123");
}
From a little more investigation it seems that it puts a / before the first non-numeric character that it encounters after a :, so:
http://example.com:a123 -> http://example.com/a123
http://example.com:12a3 -> http://example.com:12/a3
http://example.com:123a -> http://example.com:123/a
Not immediately obvious, but makes sense, I guess.

Related

Send and receive a w3c.dom.Document over socket as byte[] Java

I send a document over socket like this:
sendFXML(asByteArray(getRequiredScene(fetchSceneRequest())));
private void sendFXML(byte[] requiredFXML) throws IOException, TransformerException {
dataOutputStream.write(requiredFXML);
dataOutputStream.flush();
}
private Document getRequiredScene(String requiredFile) throws IOException, ParserConfigurationException, SAXException, TransformerException {
return new XMLLocator().getDocumentOrReturnNull(requiredFile);
}
private String fetchSceneRequest() throws IOException, ClassNotFoundException {
return dataInputStream.readUTF();
}
On the side of XMLLocator it finds the correct document and parses it right. I see it by printing the whole doc in console.
But I cannot handle it on the clients side where it's fetch by:
public static void receivePage() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] data = new byte[989898];
int bytesRead = -1;
while((bytesRead = dataInputStream.read(data)) != -1 ) { //stops here
baos.write(data, 0, bytesRead );
}
Files.write(Paths.get(FILE_TO_RECEIVED), data);
}
After the first iteration in while() cycle it just stops on the commented place.
I don't know if I have an error on the side of the server and I send this in doc in an incorrect format or I read the sent byte array incorrectly. Where is the problem?
Edit:
For the debug purpose, in the receivePage() method, I've chosen a different way of reading the byte array from server which goes like:
int count = inputStream.available();
byte[] b = new byte[count];
int bytes = dataInputStream.read(b);
System.out.println(bytes);
for (byte by : b) {
System.out.print((char)by);
}
And now I'm able to print fetched FXLM in console but a new problem has appeared.
On debug, it normally receives the byte[] from server, writes 2024 for count and displayes the content of the file but if I run the app normally via Shift + f10 it fetches nothing and just writes 0 in console
Edit2:
For some reason, once again, on debug, it's able to even write into a file
for (byte by : b) {
Files.write(Paths.get(FILE_TO_RECEIVED), b);
System.out.print((char)by);
}
But when I try to return this fxml on debug and then show like this:
Parent fxmlToShow = FXMLLoader.load(getClass().getResource("/network/gui.fxml"));
Scene childScene = new Scene(fxmlToShow);
Stage window = (Stage)((Node)ae.getSource()).getScene().getWindow();
window.setScene(childScene);
return window;
It shows only previous files. Like on the first attempt of debug it show a blank page when I asked for the 1st one from server. On the second attempt of debug when i ask for 3rd page from server, it shows me the previously asked one and so on.
To me, it seems absolutely insane cuz the fxml rile actually refreshes before the line
Parent fxmlToShow = FXMLLoader.load(getClass().getResource("/network/gui.fxml"));
is invoked.
Yeah, thank everybody for participating.
So, the issue of incorrect displaying if FXML files was caused by the incorrect FILE_TO_RECEIVED path.
When FXMLLoader.load(getClass().getResource("/network/gui.fxml")); loads gui.fxml it takes it not from D:\\JetBrains\\IdeaProjects\\Client\\src\\network\\gui.fxml,im my case, but from D:\\JetBrains\\IdeaProjects\\Client\\OUT\\PRODUCTION\\Client\\network\\gui.fxml.
As for me, that doesn't seem obvious.
What about different behaviour on debug and on run. In method receivePage() it needs to wait until connection is available.
int count = inputStream.available();
If you read docs for this method you will see
Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream ...
The available method for class InputStream always returns 0...
So, you jext need to wait for connection to be available
while(inputStream.available()==0){
Thread.sleep(100);
}
Otherwise it just prepares byte[] b = new byte[count]; for 0 bytes and you can write in nothing.

whats is happening in this apex code?

String color1 = moreColors.get(0);
String color2 = moreColors[0];
System.assertEquals(color1, color2);
// Iterate over a list to read elements
for(Integer i=0;i<colors.size();i++) {
// Write value to the debug log
System.debug(colors[i]);
}
I am learning Apex and just started what is meaning of line System.assertEquals(color1, color2); and what is mean by debug log here?
System.assert, System.assertEquals, System.assertNotEquals. I argue these are three of the most important method calls in Apex.
These are assert statements. They are used in testing to validate that the data you have matches your expectations.
System.assert tests an logical statement. If the statement evaluates to True, the code keeps running. If the statement evaluates to False, the code throws an exception.
System.assertEquals tests that two values are equal. If the two are equal, the code keeps running. If they are not equal, the code throws an exception.
System.assertNotEqual tests that two values are not equal. If the two are not equal, the code keeps running. If they are equal, the code throws an exception.
These are critical for completing system testing. In Apex Code, you must have 75% line test coverage. Many people do this by generating test code that simply covers 75% of their lines of code. However, this is an incomplete test. A good test class actually tests that the code does what you expect. This is really great to ensure that your code actually works. This makes debugging and regression testing far easier. For example. Lets create a method called square(Integer i) that squares the integer returned.
public static Integer square( Integer i ) {
return i * i;
}
A poor test method would simply be:
#isTest
public static void test_squar() {
square( 1 );
}
A good test method could be:
#isTest
public static void test_square() {
Integer i;
Integer ret_square;
i = 3;
ret_square = square( i );
System.assertEquals( i * i; ret_square );
}
How I would probably write it is like this:
#isTest
public static void test_square() {
for( Integer i = 0; i < MAX_TEST_RUNS; i++ ) {
System.assertEquals( i*i, square( i ) );
}
}
Good testing practices are integral to being a good developer. Look up more on Testing-Driven Development. https://en.wikipedia.org/wiki/Test-driven_development
Line by Line ...
//Get color in position 0 of moreColors list using the list get method store in string color1
String color1 = moreColors.get(0);
//Get color in position 0 of moreColors list using array notation store in string color2,
//basically getting the same value in a different way
String color2 = moreColors[0];
//Assert that the values are the same, throws exception if false
System.assertEquals(color1, color2);
// Iterate over a list to read elements
for(Integer i=0;i<colors.size();i++) {
// Write value to the debug log
System.debug(colors[i]);//Writes the value of color list ith position to the debug log
}
If you are running this code anonymously via the Developer console you can look for lines prefixed with DEBUG| to find the statements, for e.g.
16:09:32:001 USER_DEBUG 1|DEBUG| blue
More about system methods can be found at https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_system.htm#apex_System_System_methods

TextEncodings.Base64Url.Decode vs Convert.FromBase64String

I was working on creating a method that would generate a JWT token. Part of the method reads a value from my web.config that services as the "secret" used to generate the hash used to create the signature for the JWT token.
<add key="MySecret" value="j39djak49H893hsk297353jG73gs72HJ3tdM37Vk397" />
Initially I tried using the following to convert the "secret" value to a byte array.
byte[] key = Convert.FromBase64String(ConfigurationManager.AppSettings["MySecret"]);
However, an exception was thrown when this line was reached ...
The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
So I looked into the OAuth code and so another method being used to change a base64 string into a byte array
byte[] key = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["MySecret"]);
This method worked without issue. To me it looks like they are doing the same thing. Changing a Base64 text value into an array of bytes. However, I must be missing something. Why does Convert.FromBase64String fail and TextEncodings.Base64Url.Decode work?
I came across the same thing when I migrated our authentication service to .NET Core. I had a look at the source code for the libraries we used in our previous implementation, and the difference is actually in the name itself.
The TextEncodings class has two types of text encoders, Base64TextEncoder and Base64UrlEncoder. The latter one modifies the string slightly so the base64 string can be used in an url.
My understanding is that it is quite common to replace + and / with - and _. As a matter of fact we have been doing the same with our handshake tokens. Additionally the padding character(s) at the end can also be removed. This leaves us with the following implementation (this is from the source code):
public class Base64UrlTextEncoder : ITextEncoder
{
public string Encode(byte[] data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
return Convert.ToBase64String(data).TrimEnd('=').Replace('+', '-').Replace('/', '_');
}
public byte[] Decode(string text)
{
if (text == null)
{
throw new ArgumentNullException("text");
}
return Convert.FromBase64String(Pad(text.Replace('-', '+').Replace('_', '/')));
}
private static string Pad(string text)
{
var padding = 3 - ((text.Length + 3) % 4);
if (padding == 0)
{
return text;
}
return text + new string('=', padding);
}
}

Need to check whether any extension is present before query string

I have written the code to check the query string
Logic::if query string is "?" should remove all the characters from the query string and print the vailid URL.
char str[] = "http://john.org/test.mp4?iufjdlwle";
char *pch;
pch = strtok(str,"?");
printf("%s\n",pch);
Output::
bash-3.2$ ./querystring
http://john.com/test.mp4
But i have to check one more case
Need to get the URL only if there is any extensions present before query string?
if No extensions are present before the query string,need to skip.
I have tried this way,
continuation of the code
char *final;
final = pch+(strlen(pch)-3);
printf("%s\n",final);
if(strcasecmp(p,"mp4"))
printf("falure case\n");
else
printf("Success case\n");
It will work for .mp4 extension alone.
Incase if i'm getting *.mpeg or *.m3u8 or *.flv as an extensions,it will fail.
Can someone guide me how to solve this problem and make it working?
A query string is what starts after a question mark ?, fine.
You should try to define what an extension is. For me, it is what can happen after a dot (.) in the last component of the url, where the components are delimited with slashes (/)
So you should do:
first remove the possible query string including the initial ?
then locate the last /
then locate the last . that occurs after the last /
If you find one, it is the starting point of the extension.
So assuming pch contains the url without any query string, you can do:
char * ix = strrchr(pch, '/');
if (ix == NULL) {
// an URL without / is rather weird, better report and abort
...
}
ix = strrchr(ix, '.');
if (ix == NULL) {
// no extension here: ignore the url
...
}
else {
// found an URL containing an extension: process it
// ix+1 points to the extension
...
}

Splitting a text file where the information are separated in different lines

So, I have a text file where the information are separated by the enter key (I don't know how to explain, I will paste the code and some stuff).
cha-cha
Fruzsina
Ede
salsa
Szilvia
Imre
Here's how the text file looks like, and I need to split it into three parts, the first being the type of the dance, and then dancer 1 and dancer 2.
using System;
using System.Collections.Generic;
using System.IO;
namespace tanciskola
{
struct tanc
{
public string tancnev;
public string tancos1;
public string tancos2;
}
class Program
{
static void Main(string[] args)
{
#region 1.feladat
StreamReader sr = new StreamReader("tancrend.txt");
tanc[] tanc = new tanc[140];
string[] elv;
int i = 0;
while (sr.Peek() != 0)
{
elv = sr.ReadLine().Split('I don't know what goes here');
tanc[i].tancnev = elv[0];
tanc[i].tancos1 = elv[1];
tanc[i].tancos2 = elv[2];
i++;
}
#endregion
Console.ReadKey();
}
}
}
Here is how I tried to solve it, although I don't really get how I should do it. The task is would be to display the first dance and the last dance, but for that I need to split it somehow.
As mentioned in my comments, you seem to have a text file where each item is on a new line, and a set of 3 lines constitutes a single 'record'. In that case, you can simply read all the lines of the file, and then create your records, like so:
var v = File.ReadLines("file path");
tancr[] tanc = new tancr[140];
for (int i = 0; i < v.Count(); i += 3)
{
tanc[i/3].tancnev= v.ElementAt(i);
tanc[i/3].tancos1 = v.ElementAt(i + 1);
tanc[i/3].tancos2 = v.ElementAt(i + 2);
}
Note: ReadLines() is better when the file size is large. If your file is small, you could use ReadAllLines() instead.
To split by the "enter character" you can use Environment.NewLine in .NET:
https://msdn.microsoft.com/en-us/library/system.environment.newline(v=vs.110).aspx
elv = sr.ReadAllText().Split(new string[] {Environment.NewLine}, StringSplitOptions.None);
This constant will contain the sequence that is specific to your OS (I'm guessing Windows).
You should be aware that the characters used for newlines is different for Windows vs. Linux/Unix. So in the rare event that someone edits your file on a different OS, you can run into problems.
On Windows, newline is a two character sequence: carriage-return + line-feed (ASCII 13 + 10). On Linux it is just line-feed. So if you wanted to be extra clever, you could first check for CRLF and if you only get one element back from Split() then try just LF.

Resources