Change your rewrite rules and the order to the following:
add_rewrite_rule('my-url/([^/]*)/?$', 'index.php?my-var=$matches[1]', 'top');
add_rewrite_rule('my-url/?$', 'index.php?my-var=main', 'top');
Why the order?
If the order would be the other way around, the first rule will always apply, so the ruleset would never reach your main page
Why the changed syntax?
To allow an additional query string to be properly processed. E.g. http://foo.bar/my-url/?my-var=foo and http://foo.bar/my-url/foo/?bar=1 should be fetched to.
Additionally: A template redirect, if you want to apply your rewrite rules to query string requests like http://foo.bar/my-url/?my-var=foo:
function custom_template_redirect(){
preg_match('/(\?|&)my-var=/', $_SERVER['REQUEST_URI'], $matches);
if (
get_query_var( 'my-var', false ) !== false &&
!empty($matches) &&
!is_admin()
) {
wp_redirect(
home_url(
'/my-url/'.(get_query_var( 'my-var' )?get_query_var( 'my-var' )."https://wordpress.stackexchange.com/":'')
)
);
exit();
}
}
add_action( 'template_redirect', 'custom_template_redirect' );