<p dir="auto">So imagine I'm building an API from a set of blueprints like</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&lt;snip from the signup.py file&gt;
signupbp = Blueprint('signupbp', __name__, url_prefix=&quot;/signup&quot;)

@signupbp.route(&quot;/&quot;)
def signup_start():
    return &quot;signup_start&quot;

@signupbp.route(&quot;/complete&quot;)
def signup_complete():
    return &quot;signup_complete&quot;"><pre class="notranslate"><code class="notranslate">&lt;snip from the signup.py file&gt;
signupbp = Blueprint('signupbp', __name__, url_prefix="/signup")

@signupbp.route("/")
def signup_start():
    return "signup_start"

@signupbp.route("/complete")
def signup_complete():
    return "signup_complete"
</code></pre></div>
<p dir="auto">then in my main.py code I do something like:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="app.register_blueprint(signupbp, url_prefix='/api')"><pre class="notranslate"><code class="notranslate">app.register_blueprint(signupbp, url_prefix='/api')
</code></pre></div>
<p dir="auto">I expect to see the following routes:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="/api/signup/                    signupbp.signup_start   
/api/signup/complete            signupbp.signup_complete
/static/&lt;path:filename&gt;         static                  "><pre class="notranslate"><code class="notranslate">/api/signup/                    signupbp.signup_start   
/api/signup/complete            signupbp.signup_complete
/static/&lt;path:filename&gt;         static                  
</code></pre></div>
<p dir="auto">What I actually see is:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="/api/                    signupbp.signup_start   
/api/complete            signupbp.signup_complete
/static/&lt;path:filename&gt;  static                  "><pre class="notranslate"><code class="notranslate">/api/                    signupbp.signup_start   
/api/complete            signupbp.signup_complete
/static/&lt;path:filename&gt;  static                  
</code></pre></div>
<p dir="auto">I imagine the url_prefixes should be additive not replacement (in the worse possible way). I've tried all combinations of <code class="notranslate">/</code> before and after the url_prefix params.</p>
<p dir="auto">This is actually a very simplified example - in my API I'm using module names to implement versioning so I can't build the URL into any part of the code before thats suggested as a solution.</p>
<p dir="auto">This is related to <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="335779821" data-permission-text="Title is private" data-url="https://github.com/pallets/flask/issues/2841" data-hovercard-type="issue" data-hovercard-url="/pallets/flask/issues/2841/hovercard" href="https://github.com/pallets/flask/issues/2841">#2841</a>, but the emphasis is different.</p>
<h3 dir="auto">Expected Behavior</h3>
<p dir="auto">Non-error exceptions should not be caught by registered error handlers.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="app.register_error_handler(HTTPException, my_error_handler)

@app.route('/path-with-slash/')
def my_route():
    return '', 204"><pre class="notranslate"><span class="pl-s1">app</span>.<span class="pl-en">register_error_handler</span>(<span class="pl-v">HTTPException</span>, <span class="pl-s1">my_error_handler</span>)

<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">route</span>(<span class="pl-s">'/path-with-slash/'</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">my_route</span>():
    <span class="pl-k">return</span> <span class="pl-s">''</span>, <span class="pl-c1">204</span></pre></div>
<p dir="auto">Attempting to visit <code class="notranslate">/path-with-slash</code> should redirect to <code class="notranslate">/path-with-slash/</code>, without invoking <code class="notranslate">my_error_handler</code>.</p>
<h3 dir="auto">Actual Behavior</h3>
<p dir="auto">As the <code class="notranslate">RequestRedirect</code> raised internally in Werkzeug is a subclass of <code class="notranslate">HTTPException</code>, <code class="notranslate">my_error_handler</code> will get called. This is unexpected because no error has occurred, and the only appropriate way to handle this case is to add boilerplate to re-raise any Werkzeug <code class="notranslate">RoutingException</code>s.</p>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>Python version: 3.7.0</li>
<li>Flask version: 1.0.2</li>
<li>Werkzeug version: 0.14.1</li>
</ul>