user3469465
user3469465

Reputation: 39

URI Regex Validation

I am trying to write a regex for my HTML input which will strict the user with some conditions. (Usually I am writing codes to break up the string - so i only know the basics of regex and couldn't achieve that)

EXAMPLE:

A good input will look like this -

/account/{AccountID}/details 

While a bad input will be like one of those -

/account{/{AccountID}/details

nor

/account/{{AccountID/details

In words :

after '/' :
Accept a camelCase string
OR
Accept '{' With Pascal String (only letters) after it and must close with '}'
AND
'{' can only be after '/'
AND
after '}' :
only '/' will be acceptable
OR
String end.

If this looks to complicated to achieve by regex, I will write it as a code.

Thanks for the helpers!

Upvotes: 0

Views: 338

Answers (2)

Manuel Romeiro
Manuel Romeiro

Reputation: 1061

The regex can be ^((\/\w+)|(\/\{\w+\}))+\/?$

Explanation:

^ -> begin of the string
$ -> end of the string 
\/\w+ -> matches /letersNumbersUnderscores
\/\{\w+\} -> the same as previous, but with { after / and } at the end
| -> OR operator with above expressions, to math /text or /{text}
(...)+ -> repeat one or more times the matches
\/?$ -> matches the / and the end (if present)

I tested the values:

/account/{AccountID}/details   -> MATCH
/account/{AccountID}/details/  -> MATCH
/account{/{AccountID}/details  -> NOT MATCH
/account/{{AccountID/details   -> NOT MATCH

Upvotes: 1

Dmitry Kostyuk
Dmitry Kostyuk

Reputation: 1459

EDIT: Added more test cases and updated the regular expression, all working.

The previous answer doesn't take into account camel casing and Pascal casing and allows for numbers and underscores that you want to filter out. My proposal is the following:

/^\/account(\/[a-zA-Z]+)*(\/\{[A-Z][a-zA-Z]+\})*(\/[a-zA-Z]+)?\/?$/

this works if I understood you syntax correctly:

/camelCase/{PascalCase}/camelCase/

If not, just let me know, I'll update my improvised unit tests in the snippet below accordingly:

const re = /^\/account(\/[a-zA-Z]+)*(\/\{[A-Z][a-zA-Z]+\})*(\/[a-zA-Z]+)?\/?$/;
const testCases = [
  {
    testString: '/account/{AccountID}/details',
    isValid: true,
  },
  {
    testString: '/account{/AccountID}/details',
    isValid: false,
  },
  {
    testString: '/account/{{AccountID/details',
    isValid: false,
  },
  {
    testString: '/account/{AccountID}',
    isValid: true,
  },
  {
    testString: '/account',
    isValid: true,
  },
  {
    testString: '/account/details/transactions/{AccountID}/{OtherParameter}/',
    isValid: true,
  },
];

testCases.forEach((testCase, i) => {
  const passed = re.test(testCase.testString);
  console.log(
    `${passed === testCase.isValid ? 'PASSED' : 'FAILED'}: Case ${i + 1} is ${
      testCase.isValid ? 'valid' : 'not valid'
    }`
  );
});

Let me know if this helps ;)

Upvotes: 1

Related Questions