elunez/eladmin · error · BadRequestException

外链必须以http://或者https://开头

Error message

外链必须以http://或者https://开头

What it means

BadRequestException thrown in MenuServiceImpl.create when a menu is flagged as an external link (iFrame = true) but its path does not start with http:// or https:// (case-insensitive). External-link menus are rendered in an iframe, so the path must be an absolute URL. The generic BAD_REQUEST constant is the message, while the Chinese literal '外链必须以http://或者https://开头' documents the rule.

Source

Thrown at eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java:136

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Menu resources) {
        if(menuRepository.findByTitle(resources.getTitle()) != null){
            throw new EntityExistException(Menu.class,"title",resources.getTitle());
        }
        if(StringUtils.isNotBlank(resources.getComponentName())){
            if(menuRepository.findByComponentName(resources.getComponentName()) != null){
                throw new EntityExistException(Menu.class,"componentName",resources.getComponentName());
            }
        }
        if (Long.valueOf(0L).equals(resources.getPid())) {
            resources.setPid(null);
        }
        if(resources.getIFrame()){
            if (!(resources.getPath().toLowerCase().startsWith(HTTP_PRE)||resources.getPath().toLowerCase().startsWith(HTTPS_PRE))) {
                throw new BadRequestException(BAD_REQUEST);
            }
        }
        menuRepository.save(resources);
        // 计算子节点数目
        resources.setSubCount(0);
        // 更新父节点菜单数目
        updateSubCnt(resources.getPid());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Menu resources) {
        if(resources.getId().equals(resources.getPid())) {
            throw new BadRequestException("上级不能为自己");
        }
        Menu menu = menuRepository.findById(resources.getId()).orElseGet(Menu::new);
        ValidationUtil.isNull(menu.getId(),"Permission","id",resources.getId());

View on GitHub (pinned to 55fbf70595)

Solutions

  1. Set the menu path to a full URL, e.g. 'https://www.baidu.com' instead of 'www.baidu.com'.
  2. In the front-end form, normalize the input: prepend 'https://' when the user omitted the scheme for iframe menus.
  3. If the target is an internal Vue page, set iFrame=false and use a relative path/component instead.

Example fix

// before
menu.setIFrame(true);
menu.setPath("www.example.com/docs"); // rejected

// after
menu.setIFrame(true);
menu.setPath("https://www.example.com/docs");
Defensive patterns

Strategy: validation

Validate before calling

if (menu.getIFrame() && !menu.getPath().toLowerCase().matches("^https?://.*")) {
    throw new IllegalArgumentException("外链必须以 http:// 或 https:// 开头");
}

Type guard

const isAbsoluteUrl = (p: string) => /^https?:\/\//i.test(p);

Prevention

When it happens

Trigger: POST /api/menus with iFrame=true and path like 'www.baidu.com' or '/external/doc' — anything not prefixed with http:// or https://.

Common situations: Admins entering a bare domain without the scheme; UI form allowing relative paths for iframe menus; data migrations that stored trimmed URLs.

Related errors


AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14). Data as JSON: /api/errors/613ded76e9533386. Report an issue: GitHub.