-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CMCD nor field should be "more" relative to the current request #3741
Comments
I will keep this in the backlog. In my opinion this is low priority, I fear that there are a lot of edge cases like for instance different levels of pathnames for the representations. Right now I prefer the solution we have in place which might create a bit of overhead but will deliver valid data |
Actually there are two problems here which should be fixed immediately as they are not spec compliant.
Both of these issues will cause a CDN to miss-construct the prefetch request. Please add this issue back to 4.1.0 milestone. |
@mgreve-akamai @wilaw Can I please ask you to have a look at the following unit tests and confirm that this is the expected path. it('Should return complete url if no original url is given', () => {
const b = 'https://localhost:3000/d/e/f.mp4';
expect(Utils.getRelativeUrl(undefined,b)).to.be.equal('https://localhost:3000/d/e/f.mp4');
})
it('Should return relative url if strings are different after server name', () => {
const a = 'https://localhost:3000/a/b/c.mp4';
const b = 'https://localhost:3000/d/e/f.mp4';
expect(Utils.getRelativeUrl(a,b)).to.be.equal('d/e/f.mp4');
})
it('Should return relative url if strings are similar up to one element before filename', () => {
const a = 'https://localhost:3000/a/b/c.mp4';
const b = 'https://localhost:3000/a/c/f.mp4';
expect(Utils.getRelativeUrl(a,b)).to.be.equal('c/f.mp4');
})
it('Should return relative url if strings are similar up to filename', () => {
const a = 'https://localhost:3000/a/b/c.mp4';
const b = 'https://localhost:3000/a/b/f.mp4';
expect(Utils.getRelativeUrl(a,b)).to.be.equal('f.mp4');
})
it('Should return complete url if origin is different', () => {
const a = 'https://localhost:3000/a/b/c.mp4';
const b = 'https://loca:3000/a/b/f.mp4';
expect(Utils.getRelativeUrl(a,b)).to.be.equal('https://loca:3000/a/b/f.mp4');
})
it('Should return relative url if part of the pathnames are not equal', () => {
const a = 'https://localhost:3000/a/b/c.mp4';
const b = 'https://localhost:3000/ab/b/f.mp4';
expect(Utils.getRelativeUrl(a,b)).to.be.equal('ab/b/f.mp4');
})
it('Should return relative url if target pathname is longer than source pathname ', () => {
const a = 'https://localhost:3000/a/b/f.mp4';
const b = 'https://localhost:3000/a/b/f/e/c.mp4';
expect(Utils.getRelativeUrl(a,b)).to.be.equal('/a/b/f/e/c.mp4');
})
it('Should return relative url if source pathname is longer than target pathname ', () => {
const a = 'https://localhost:3000/a/b/f/e/c.mp4';
const b = 'https://localhost:3000/a/b/f.mp4';
expect(Utils.getRelativeUrl(a,b)).to.be.equal('../../f.mp4');
}) |
I looked over the examples, and I think a number of them are incorrect. I'll list them below: I think this test is incorrect.
It should be '/d/e/f.mp4' (with 'd/e/f.mp4' as in the test, the new url would be https://localhost:3000/a/b/d/e/f.mp4). This one is also incorrect.
It should be '../c/f.mp4' or '/a/c/f.mp4' This one is also incorrect:
It should be '../../ab/b/f.mp4' or '/ab/b/f.mp4' (the latter is shorter. The second-to-last is longer than needed:
The shorter answer is 'f/e/c.mp4'. This last one is correct:
An unrelated point to the test cases: What if the scheme (https vs. https) changes? I'm wondering if you want tests for that and what's the intended behavior in this case (?). Hopefully, I got all of them correct :) |
I've written an implementation of this function, which is think is fairly straightforward and I think it's correct :). It has no error handling for the case of different hosts etc. It has the correct (and optimal) answers for the test cases. There may be an error or two in my comment above, which I spotted while building this (I have not edited my comment above). Feel free to adapt and use parts of this code if you think it's useful.
|
Thanks @mgreve-akamai that was very helpful. I used parts of your sample code for the implementation but moved to the path module: static getRelativeUrl(originalUrl, targetUrl) {
try {
const original = new URL(originalUrl);
const target = new URL(targetUrl);
// Unify the protocol to compare the origins
original.protocol = target.protocol;
if (original.origin !== target.origin) {
return targetUrl;
}
// Use the relative path implementation of the path library. We need to cut off the actual filename in the end to get the relative path
let relativePath = path.relative(original.pathname.substr(0, original.pathname.lastIndexOf('/')), target.pathname.substr(0, target.pathname.lastIndexOf('/')));
// In case the relative path is empty (both path are equal) return the filename only. Otherwise add a slash in front of the filename
const startIndexOffset = relativePath.length === 0 ? 1 : 0;
relativePath += target.pathname.substr(target.pathname.lastIndexOf('/') + startIndexOffset, target.pathname.length - 1);
// Build the other candidate, e.g. the 'host relative' path that starts with "/", and return the shortest of the two candidates.
if (target.pathname.length < relativePath.length) {
return target.pathname;
}
return relativePath;
} catch (e) {
return targetUrl
}
} You can find the corresponding pull request here: #3747 . Please let me know if you encounter any issues. One specific thing to mention is that I treat origins with different protocols as if they have the same protocol (https vs http). If that should be changed let me know. it('Should return filename if origin differs in terms of SSL', () => {
const a = 'https://localhost:3000/a/b/c.mp4';
const b = 'http://localhost:3000/a/b/e.mp4';
expect(Utils.getRelativeUrl(a,b)).to.be.equal('e.mp4');
}) |
Closing this, please comment if you encounter any problems |
Environment
Steps to reproduce
Play the stream on the CMCD sample page: https://reference.dashif.org/dash.js/nightly/samples/advanced/cmcd.html
Observed behavior
The CMCD nor field is always sent relative to the root of the URL, which is somewhat inefficient. Here's an example from the textarea on the CMCD sample page:
type: video
file: bbb_30fps_3840x2160_12000k_15.m4v
bl : 56000
br : 14931
cid : 21cf726cfe3d937b5f974f72bb5bd06a
d : 4000
dl : 56000
mtp : 171600
nor : /akamai/bbb_30fps/bbb_30fps_3840x2160_12000k/bbb_30fps_3840x2160_12000k_16.m4v
ot : v
rtp : 5400
sf : d
sid : b248658d-1d1a-4039-91d0-8c08ba597da5
st : v
tb : 14932
v : 1
type: audio
file: bbb_a64k_14.m4a
bl : 52100
br : 67
cid : 21cf726cfe3d937b5f974f72bb5bd06a
d : 4011
dl : 52100
mtp : 1500
nor : /akamai/bbb_30fps/bbb_a64k/bbb_a64k_15.m4a
ot : a
rtp : 100
sf : d
sid : b248658d-1d1a-4039-91d0-8c08ba597da5
st : v
tb : 67
v : 1
Console output
Irrelevant
Expected behavior
In the two cases above, the most efficient value (in terms of request size) for the nor field is:
nor: bbb_30fps_3840x2160_12000k/bbb_30fps_3840x2160_12000k_16.m4v
nor: bbb_a64k_15.m4a
For reference, here's one full URL: https://dash.akamaized.net/akamai/bbb_30fps/bbb_a64k/bbb_a64k_1.m4a, where you can see that the /akamai/bbb_30fps/ components are always present, and hence don't need to be repeated in the nor field. Technically, what dash.js is doing is not incorrect - rather it's not efficient given that URLs in practice can be very long.
The text was updated successfully, but these errors were encountered: