Authenticated access to bitbucket URLs from inside bitbucket plugin/URL component extraction


I’m trying to access an authenticated Bitbucket Server URL from within a Bitbucket server hook/servlet. I have it working but I feel like I’m going round the houses to do things like parse/split URLs. I’ve searched to see if this is built-in functionality but couldn’t find anything. Does anyone know a better way of doing this?

I want users to be able to configure my hook by pasting a URL into its settings screen that contains rules the plugin will use. The URL could be one referencing a file hosted inside a bitbucket repo or on the Internet. If anyone knows an easy way to cache this that would be really helpful too.


  • http://bitbucket:7990/bitbucket/projects/RUL/repos/rules/raw/test.json --> grab the URL inside the hook as the logged on user
  • --> grab the URL inside the hook, no authentication (unless specified inside the URL)

I wasn’t able to get this to pass on the user’s current credentials. The closest thing I saw were questions about using SAL TrustedRequestFactory with Jira and Bamboo:

I tried injecting TrustedRequestFactory in Bitbucket with @ComponentImport but I get missing class errors. I defined sal-trust-api in my pom.xml with variants of:

       <scope>provided</scope> <!-- on and off -->

… But nothing seemed to help. Looks like its just not supported in Bitbucket (5.16.0)?

The closest thing I could find that did work was based on another forum post which shows how to use the Java API to request files based on project keys and repository slugs:

I couldn’t see an easy way to extract these strings from a URL so I ended up writing my own[1] - surely this already exists somewhere? Anyone know what it called?

After a day of hacking around my working code looks like this (constructor injection used for contentService, applicationProperties and requestFactory):

        String baseUrl = applicationProperties.getBaseUrl(UrlMode.ABSOLUTE);
        BitbucketUrl bitbucketUrl = new BitbucketUrl(baseUrl, customRuleUrl);
        InputStream in;
        if (bitbucketUrl.isBitbucketUrl()) {
            // grab a file from local bitbucket instance using Java API
            Repository repository = repositoryService.getBySlug(

            ByteArrayOutputStream out = new ByteArrayOutputStream();
                    (s) -> out

            in = new ByteArrayInputStream(out.toByteArray());
        } else {
            // non-local URL - just make a regular request using RequestFactory
            in = (InputStream) requestFactory.createRequest(Request.MethodType.GET, customRuleUrl)


Can anyone help me simplify this?


[1] Bitbucket URL component extractor

package com.declarativesystems.bitbucket.commitscanner;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BitbucketUrl {

    private String project;
    private String slug;
    private String filePath;
    private String revision;
    private boolean bitbucketUrl;
    private Matcher matcher;

    public String getProject() {
        return project;

    public String getSlug() {
        return slug;

    public String getFilePath() {
        return filePath;

    public String getRevision() {
        return revision;

     * /projects/RUL/repos/rules/raw/test.json
     * URLs must match this regex which we also use for field capture:
     * $1 - project key
     * $2 - slug/repository name
     * $3 - path
     * $4 - at parameter (all)
     * $5 - commit/branch
    private static final Pattern regex = Pattern.compile(

    public BitbucketUrl(String baseUrl, String targetUrl) {
        bitbucketUrl = targetUrl.startsWith(baseUrl);
        if (bitbucketUrl) {
            parseBitbucketUrl(targetUrl.replace(baseUrl, ""));


     * should be left with something like
     * /projects/RUL/repos/rules/raw/test.json
    private void parseBitbucketUrl(String path) {
        // only allow paths matching regex we expect
        matcher = regex.matcher(path);
        if (matcher.matches()) {
            project =;
            slug =;
            filePath =;
            revision =;
        } else {
            throw new RuntimeException(
                "Access denied: only files from bitbucket repositories can be accessed"

    public boolean isBitbucketUrl() {
        return bitbucketUrl && matcher.matches();