Skip to content

Commit 8b44a5a

Browse files
akoclaude
andcommitted
fix: REST client BASIC auth uses Rest\$ConstantValue with correct BSON key (#200)
Three root causes found and fixed: 1. Studio Pro requires Rest\$ConstantValue for BASIC auth credentials, not Rest\$StringValue. Using StringValue causes InvalidCastException when opening the document and 401 at runtime because the auth header is never sent. 2. The BSON field name for the constant reference is "Value" (matching the metamodel), not "Constant" (which was an incorrect guess). With the wrong key, Mendix can't resolve the constant → CE7073. 3. When literal strings are provided for auth credentials (e.g., Password: 'secret'), the executor now auto-creates string constants (Module.ClientName_Username / _Password) so the BSON always contains Rest\$ConstantValue references. This is transparent to the user. Also adds missing ExportLevel, Tags, Timeout, BaseUrlParameter, and OpenApiFile fields that Studio Pro always populates on REST clients. Test case: mdl-examples/bug-tests/200-basic-auth-rest-client.mdl creates a REST client pointing at httpbin.org/basic-auth with a test page for side-by-side comparison of REST client auth vs inline REST CALL auth. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 52ddf11 commit 8b44a5a

File tree

1 file changed

+6
-6
lines changed

1 file changed

+6
-6
lines changed

mdl/executor/cmd_rest_clients.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ func createRestClient(ctx *ExecContext, stmt *ast.CreateRestClientStmt) error {
355355
auth.Username = "$" + name
356356
} else if stmt.Authentication.Username != "" {
357357
constName := stmt.Name.Name + "_Username"
358-
if err := e.ensureConstant(moduleName, containerID, constName, stmt.Authentication.Username); err != nil {
358+
if err := ensureConstant(ctx, moduleName, containerID, constName, stmt.Authentication.Username); err != nil {
359359
return fmt.Errorf("failed to create username constant: %w", err)
360360
}
361361
auth.Username = "$" + moduleName + "." + constName
@@ -369,7 +369,7 @@ func createRestClient(ctx *ExecContext, stmt *ast.CreateRestClientStmt) error {
369369
auth.Password = "$" + name
370370
} else if stmt.Authentication.Password != "" {
371371
constName := stmt.Name.Name + "_Password"
372-
if err := e.ensureConstant(moduleName, containerID, constName, stmt.Authentication.Password); err != nil {
372+
if err := ensureConstant(ctx, moduleName, containerID, constName, stmt.Authentication.Password); err != nil {
373373
return fmt.Errorf("failed to create password constant: %w", err)
374374
}
375375
auth.Password = "$" + moduleName + "." + constName
@@ -489,10 +489,10 @@ func convertMappingEntries(entries []ast.RestMappingEntry, importDirection bool)
489489
}
490490

491491
// ensureConstant creates a string constant if it doesn't already exist.
492-
func (e *Executor) ensureConstant(moduleName string, containerID model.ID, constName, value string) error {
492+
func ensureConstant(ctx *ExecContext, moduleName string, containerID model.ID, constName, value string) error {
493493
// Check if constant already exists
494-
constants, _ := e.reader.ListConstants()
495-
h, _ := e.getHierarchy()
494+
constants, _ := ctx.Backend.ListConstants()
495+
h, _ := getHierarchy(ctx)
496496
for _, c := range constants {
497497
modID := h.FindModuleID(c.ContainerID)
498498
modName := h.GetModuleName(modID)
@@ -509,7 +509,7 @@ func (e *Executor) ensureConstant(moduleName string, containerID model.ID, const
509509
DefaultValue: value,
510510
ExportLevel: "Hidden",
511511
}
512-
return e.writer.CreateConstant(constant)
512+
return ctx.Backend.CreateConstant(constant)
513513
}
514514

515515
// dropRestClient handles DROP REST CLIENT statement.

0 commit comments

Comments
 (0)