1- import { describe , it , expect } from 'vitest'
2- import { extractApiVersionFromUrl , isAzureOpenAiUrl , removeApiVersionFromUrl } from '../azure-url-parser'
1+ import { describe , it , expect } from "vitest"
2+ import {
3+ extractApiVersionFromUrl ,
4+ isAzureOpenAiUrl ,
5+ removeApiVersionFromUrl ,
6+ isValidAzureApiVersion ,
7+ } from "../azure-url-parser"
8+
9+ describe ( "azure-url-parser" , ( ) => {
10+ describe ( "isValidAzureApiVersion" , ( ) => {
11+ it ( "should return true for valid API version format YYYY-MM-DD" , ( ) => {
12+ expect ( isValidAzureApiVersion ( "2024-05-01" ) ) . toBe ( true )
13+ expect ( isValidAzureApiVersion ( "2023-12-31" ) ) . toBe ( true )
14+ } )
15+
16+ it ( "should return true for valid API version format YYYY-MM-DD-preview" , ( ) => {
17+ expect ( isValidAzureApiVersion ( "2024-05-01-preview" ) ) . toBe ( true )
18+ expect ( isValidAzureApiVersion ( "2024-12-01-preview" ) ) . toBe ( true )
19+ } )
20+
21+ it ( "should return false for invalid API version formats" , ( ) => {
22+ expect ( isValidAzureApiVersion ( "2024-5-1" ) ) . toBe ( false ) // Missing leading zeros
23+ expect ( isValidAzureApiVersion ( "24-05-01" ) ) . toBe ( false ) // Two-digit year
24+ expect ( isValidAzureApiVersion ( "2024/05/01" ) ) . toBe ( false ) // Wrong separator
25+ expect ( isValidAzureApiVersion ( "2024-05-01-alpha" ) ) . toBe ( false ) // Wrong suffix
26+ expect ( isValidAzureApiVersion ( "invalid-version" ) ) . toBe ( false )
27+ expect ( isValidAzureApiVersion ( "" ) ) . toBe ( false )
28+ } )
29+ } )
330
4- describe ( 'azure-url-parser' , ( ) => {
5- describe ( 'extractApiVersionFromUrl' , ( ) => {
6- it ( 'should extract API version from Azure OpenAI URL' , ( ) => {
7- const url = ' https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version=2024-05-01-preview'
31+ describe ( "extractApiVersionFromUrl" , ( ) => {
32+ it ( "should extract API version from Azure OpenAI URL" , ( ) => {
33+ const url =
34+ " https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version=2024-05-01-preview"
835 const result = extractApiVersionFromUrl ( url )
9- expect ( result ) . toBe ( ' 2024-05-01-preview' )
36+ expect ( result ) . toBe ( " 2024-05-01-preview" )
1037 } )
1138
12- it ( 'should extract API version from URL with multiple query parameters' , ( ) => {
13- const url = 'https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?foo=bar&api-version=2024-12-01-preview&baz=qux'
39+ it ( "should extract API version from URL with multiple query parameters" , ( ) => {
40+ const url =
41+ "https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?foo=bar&api-version=2024-12-01-preview&baz=qux"
1442 const result = extractApiVersionFromUrl ( url )
15- expect ( result ) . toBe ( ' 2024-12-01-preview' )
43+ expect ( result ) . toBe ( " 2024-12-01-preview" )
1644 } )
1745
18- it ( ' should return null when no api-version parameter exists' , ( ) => {
19- const url = ' https://api.openai.com/v1/chat/completions'
46+ it ( " should return null when no api-version parameter exists" , ( ) => {
47+ const url = " https://api.openai.com/v1/chat/completions"
2048 const result = extractApiVersionFromUrl ( url )
2149 expect ( result ) . toBeNull ( )
2250 } )
2351
24- it ( ' should return null for invalid URLs' , ( ) => {
25- const invalidUrl = ' not-a-valid-url'
52+ it ( " should return null for invalid URLs" , ( ) => {
53+ const invalidUrl = " not-a-valid-url"
2654 const result = extractApiVersionFromUrl ( invalidUrl )
2755 expect ( result ) . toBeNull ( )
2856 } )
2957
30- it ( ' should handle empty api-version parameter' , ( ) => {
31- const url = ' https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version='
58+ it ( " should handle empty api-version parameter" , ( ) => {
59+ const url = " https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version="
3260 const result = extractApiVersionFromUrl ( url )
33- expect ( result ) . toBe ( '' )
61+ expect ( result ) . toBe ( "" )
3462 } )
3563
36- it ( ' should handle URL without query parameters' , ( ) => {
37- const url = ' https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions'
64+ it ( " should handle URL without query parameters" , ( ) => {
65+ const url = " https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions"
3866 const result = extractApiVersionFromUrl ( url )
3967 expect ( result ) . toBeNull ( )
4068 } )
69+
70+ it ( "should handle URL with duplicate api-version parameters" , ( ) => {
71+ const url =
72+ "https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version=2024-05-01&api-version=2024-12-01"
73+ const result = extractApiVersionFromUrl ( url )
74+ // URL.searchParams.get returns the first value
75+ expect ( result ) . toBe ( "2024-05-01" )
76+ } )
77+
78+ it ( "should handle URL with malformed api-version parameter" , ( ) => {
79+ const url =
80+ "https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version=invalid-format"
81+ const result = extractApiVersionFromUrl ( url )
82+ expect ( result ) . toBe ( "invalid-format" ) // Still extracts it, validation is separate
83+ } )
4184 } )
4285
43- describe ( ' isAzureOpenAiUrl' , ( ) => {
44- it ( ' should return true for Azure OpenAI URLs with .openai.azure.com' , ( ) => {
45- const url = ' https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions'
86+ describe ( " isAzureOpenAiUrl" , ( ) => {
87+ it ( " should return true for Azure OpenAI URLs with .openai.azure.com" , ( ) => {
88+ const url = " https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions"
4689 const result = isAzureOpenAiUrl ( url )
4790 expect ( result ) . toBe ( true )
4891 } )
4992
50- it ( ' should return true for Azure URLs ending with .azure.com' , ( ) => {
51- const url = ' https://myservice.azure.com/api/v1'
93+ it ( " should return true for Azure URLs ending with .azure.com" , ( ) => {
94+ const url = " https://myservice.azure.com/api/v1"
5295 const result = isAzureOpenAiUrl ( url )
5396 expect ( result ) . toBe ( true )
5497 } )
5598
56- it ( ' should return true for URLs with /openai/deployments/ path' , ( ) => {
57- const url = ' https://custom-domain.com/openai/deployments/mymodel/chat/completions'
99+ it ( " should return true for URLs with /openai/deployments/ path" , ( ) => {
100+ const url = " https://custom-domain.com/openai/deployments/mymodel/chat/completions"
58101 const result = isAzureOpenAiUrl ( url )
59102 expect ( result ) . toBe ( true )
60103 } )
61104
62- it ( ' should return false for regular OpenAI URLs' , ( ) => {
63- const url = ' https://api.openai.com/v1/chat/completions'
105+ it ( " should return false for regular OpenAI URLs" , ( ) => {
106+ const url = " https://api.openai.com/v1/chat/completions"
64107 const result = isAzureOpenAiUrl ( url )
65108 expect ( result ) . toBe ( false )
66109 } )
67110
68- it ( ' should return false for other API URLs' , ( ) => {
69- const url = ' https://api.anthropic.com/v1/messages'
111+ it ( " should return false for other API URLs" , ( ) => {
112+ const url = " https://api.anthropic.com/v1/messages"
70113 const result = isAzureOpenAiUrl ( url )
71114 expect ( result ) . toBe ( false )
72115 } )
73116
74- it ( ' should return false for invalid URLs' , ( ) => {
75- const invalidUrl = ' not-a-valid-url'
117+ it ( " should return false for invalid URLs" , ( ) => {
118+ const invalidUrl = " not-a-valid-url"
76119 const result = isAzureOpenAiUrl ( invalidUrl )
77120 expect ( result ) . toBe ( false )
78121 } )
79122
80- it ( ' should handle case insensitive hostname matching' , ( ) => {
81- const url = ' https://MYRESOURCE.OPENAI.AZURE.COM/openai/deployments/mymodel'
123+ it ( " should handle case insensitive hostname matching" , ( ) => {
124+ const url = " https://MYRESOURCE.OPENAI.AZURE.COM/openai/deployments/mymodel"
82125 const result = isAzureOpenAiUrl ( url )
83126 expect ( result ) . toBe ( true )
84127 } )
128+
129+ it ( "should return false for malicious URLs trying to include Azure domain" , ( ) => {
130+ const maliciousUrl = "https://evil.openai.azure.com.attacker.com/api/v1"
131+ const result = isAzureOpenAiUrl ( maliciousUrl )
132+ expect ( result ) . toBe ( false )
133+ } )
134+
135+ it ( "should return true for root openai.azure.com domain" , ( ) => {
136+ const url = "https://openai.azure.com/api/v1"
137+ const result = isAzureOpenAiUrl ( url )
138+ expect ( result ) . toBe ( true )
139+ } )
140+
141+ it ( "should return false for Azure AI Inference Service URLs" , ( ) => {
142+ const url = "https://myservice.services.ai.azure.com/models/deployments"
143+ const result = isAzureOpenAiUrl ( url )
144+ expect ( result ) . toBe ( false )
145+ } )
85146 } )
86147
87- describe ( 'removeApiVersionFromUrl' , ( ) => {
88- it ( 'should remove api-version parameter from URL' , ( ) => {
89- const url = 'https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version=2024-05-01-preview'
148+ describe ( "removeApiVersionFromUrl" , ( ) => {
149+ it ( "should remove api-version parameter from URL" , ( ) => {
150+ const url =
151+ "https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version=2024-05-01-preview"
90152 const result = removeApiVersionFromUrl ( url )
91- expect ( result ) . toBe ( ' https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions' )
153+ expect ( result ) . toBe ( " https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions" )
92154 } )
93155
94- it ( 'should remove api-version parameter while preserving other parameters' , ( ) => {
95- const url = 'https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?foo=bar&api-version=2024-05-01-preview&baz=qux'
156+ it ( "should remove api-version parameter while preserving other parameters" , ( ) => {
157+ const url =
158+ "https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?foo=bar&api-version=2024-05-01-preview&baz=qux"
96159 const result = removeApiVersionFromUrl ( url )
97- expect ( result ) . toBe ( 'https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?foo=bar&baz=qux' )
160+ expect ( result ) . toBe (
161+ "https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?foo=bar&baz=qux" ,
162+ )
98163 } )
99164
100- it ( ' should return original URL when no api-version parameter exists' , ( ) => {
101- const url = ' https://api.openai.com/v1/chat/completions?foo=bar'
165+ it ( " should return original URL when no api-version parameter exists" , ( ) => {
166+ const url = " https://api.openai.com/v1/chat/completions?foo=bar"
102167 const result = removeApiVersionFromUrl ( url )
103168 expect ( result ) . toBe ( url )
104169 } )
105170
106- it ( ' should return original URL for invalid URLs' , ( ) => {
107- const invalidUrl = ' not-a-valid-url'
171+ it ( " should return original URL for invalid URLs" , ( ) => {
172+ const invalidUrl = " not-a-valid-url"
108173 const result = removeApiVersionFromUrl ( invalidUrl )
109174 expect ( result ) . toBe ( invalidUrl )
110175 } )
111176
112- it ( 'should handle URL with only api-version parameter' , ( ) => {
113- const url = 'https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version=2024-05-01-preview'
177+ it ( "should handle URL with only api-version parameter" , ( ) => {
178+ const url =
179+ "https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions?api-version=2024-05-01-preview"
114180 const result = removeApiVersionFromUrl ( url )
115- expect ( result ) . toBe ( ' https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions' )
181+ expect ( result ) . toBe ( " https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions" )
116182 } )
117183
118- it ( ' should handle URL without query parameters' , ( ) => {
119- const url = ' https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions'
184+ it ( " should handle URL without query parameters" , ( ) => {
185+ const url = " https://myresource.openai.azure.com/openai/deployments/mymodel/chat/completions"
120186 const result = removeApiVersionFromUrl ( url )
121187 expect ( result ) . toBe ( url )
122188 } )
123189 } )
124- } )
190+ } )
0 commit comments