@@ -11,6 +11,12 @@ const HTTPS_SCHEMA: string = 'https://';
1111// eslint-disable-next-line @typescript-eslint/typedef
1212const ALPHABET_REGEX = / ^ [ a - z A - Z ] + $ / ;
1313
14+ export interface ParsedSqsUrl {
15+ queueName : string ;
16+ accountId : string ;
17+ region ?: string ;
18+ }
19+
1420export class SqsUrlParser {
1521 /**
1622 * Best-effort logic to extract queue name from an HTTP url. This method should only be used with
@@ -23,7 +29,7 @@ export class SqsUrlParser {
2329 if ( typeof url !== 'string' ) {
2430 return undefined ;
2531 }
26- const urlWithoutProtocol = this . removeProtocol ( url ) ;
32+ const urlWithoutProtocol = url . replace ( HTTP_SCHEMA , '' ) . replace ( HTTPS_SCHEMA , '' ) ;
2733 const splitUrl : string [ ] = urlWithoutProtocol . split ( '/' ) ;
2834 if ( splitUrl . length === 3 && isAccountId ( splitUrl [ 1 ] ) && this . isValidQueueName ( splitUrl [ 2 ] ) ) {
2935 return splitUrl [ 2 ] ;
@@ -39,13 +45,8 @@ export class SqsUrlParser {
3945 return undefined ;
4046 }
4147
42- if ( this . isValidSqsUrl ( url ) ) {
43- const urlWithoutProtocol = this . removeProtocol ( url ) ;
44- const splitUrl : string [ ] = urlWithoutProtocol . split ( '/' ) ;
45- return splitUrl [ 1 ] ;
46- }
47-
48- return undefined ;
48+ const parsedUrl = this . parseUrl ( url ) ;
49+ return parsedUrl ?. accountId ;
4950 }
5051
5152 /**
@@ -56,37 +57,43 @@ export class SqsUrlParser {
5657 return undefined ;
5758 }
5859
59- if ( this . isValidSqsUrl ( url ) ) {
60- const urlWithoutProtocol = this . removeProtocol ( url ) ;
61- const splitUrl : string [ ] = urlWithoutProtocol . split ( '/' ) ;
62- const domain : string = splitUrl [ 0 ] ;
63- const domainParts : string [ ] = domain . split ( '.' ) ;
64- if ( domainParts . length === 4 ) {
65- return domainParts [ 1 ] ;
66- }
60+ const parsedUrl = this . parseUrl ( url ) ;
61+ return parsedUrl ?. region ;
62+ }
63+
64+ /**
65+ * Parses an SQS URL and extracts its components.
66+ * Format: https://sqs.<region>.amazonaws.com/<accountId>/<queueName>
67+ * @param url - The SQS URL to parse
68+ * @returns Object containing queue name, account ID and region, or undefined if invalid
69+ * @private
70+ */
71+ private static parseUrl ( url : string ) : ParsedSqsUrl | undefined {
72+ const urlWithoutProtocol = url . replace ( HTTP_SCHEMA , '' ) . replace ( HTTPS_SCHEMA , '' ) ;
73+ const splitUrl = urlWithoutProtocol . split ( '/' ) ;
74+
75+ if (
76+ splitUrl . length !== 3 ||
77+ ! splitUrl [ 0 ] . toLowerCase ( ) . startsWith ( 'sqs' ) ||
78+ ! isAccountId ( splitUrl [ 1 ] ) ||
79+ ! this . isValidQueueName ( splitUrl [ 2 ] )
80+ ) {
81+ return undefined ;
6782 }
6883
69- return undefined ;
70- }
84+ const domain = splitUrl [ 0 ] ;
85+ const domainParts = domain . split ( '.' ) ;
7186
72- private static removeProtocol ( url : string ) : string {
73- return url . replace ( HTTP_SCHEMA , '' ) . replace ( HTTPS_SCHEMA , '' ) ;
87+ return {
88+ queueName : splitUrl [ 2 ] ,
89+ accountId : splitUrl [ 1 ] ,
90+ region : domainParts . length === 4 ? domainParts [ 1 ] : undefined ,
91+ } ;
7492 }
7593
7694 /**
7795 * Checks if the URL is a valid SQS URL.
7896 */
79- private static isValidSqsUrl ( url : string ) : boolean {
80- const urlWithoutProtocol = this . removeProtocol ( url ) ;
81- const splitUrl : string [ ] = urlWithoutProtocol . split ( '/' ) ;
82- return (
83- splitUrl . length === 3 &&
84- splitUrl [ 0 ] . toLowerCase ( ) . startsWith ( 'sqs' ) &&
85- isAccountId ( splitUrl [ 1 ] ) &&
86- this . isValidQueueName ( splitUrl [ 2 ] )
87- ) ;
88- }
89-
9097 private static isValidQueueName ( input : string ) : boolean {
9198 if ( input == null || input . length === 0 || input . length > 80 ) {
9299 return false ;
0 commit comments