I was filtering URLs for pageAction with hostSuffix according to this SO answer: How to show Chrome Extension on certain domains?
var onWebNav = function(details){ if (details.frameId === 0) chrome.pageAction.show(details.tabId); };
var filter = { url: [{ hostSuffix: "reddit.com" }] };
chrome.webNavigation.onCommitted.addListener(onWebNav, filter);
chrome.webNavigation.onHistoryStateUpdated.addListener(onWebNav, filter);
But if I want a pattern, like http://*.reddit.com/r/*/comments/*, I should use schemes instead of hostSuffix, right? According to https://developer.chrome.com/extensions/match_patterns this should match everything:
var filter = { url: [{ schemes: ["http://*/*"] }] };
but it doesn't match even this URL http://www.reddit.com/r/IAmA/comments/z1c9z/.
Do I use schemes filter in wrong way?
I don't think that is a valid scheme. A scheme is what identifies the protocol used, it shouldn't have any wildcards.
The match_patterns link describes a fully build up pattern, consisting of 3 parts, including a scheme. This is a different system from the one you're trying to use, which is based on matching different parts of an URL separately. The patterns link does give you info on valid schemes, in the basic syntax table:
<scheme> := '*' | 'http' | 'https' | 'file' | 'ftp'
Try var filter = { url: [{ schemes: ["http"] }] }; instead. This should match any URL that goes over plain old HTTP.
To achieve your desired matching, the best thing would be to use either the originAndPathMatches or urlMatches filters, since you need the regular expression for matching the host and the specific syntax of the path.
Related
I'm building a URL Shortener, and I've decided to recyle the short ID's if possible to save space in my database. How can i check if 2 URL's lead to the same path?
For example, let's say a user generates a short URL for https://google.com/.
My app generates the following short id: jkU3
So if this user visits https://tiny.url/jkU3 my express server will redirect the visitor to https://google.com/.
This works like a charm, but know let's imagine another person visits https://tiny.url/ and generates a short URL for https://google.com. And another one comes and generates a short URL for https://www.google.com/, and another one comes and generates one for https://www.google.com. You get the point..
So far my app would have wasted 4 short ID's.
How can i prevent this from happening? Is there a regex for this?
This is the current code I have for generating short URL's:
app.post("/", (req: Request, res: Response) => {
const shortUrl: string = nanoid(4);
const destination: string = req.body.destination;
UrlSchema.create({
_id: mongoose.Types.ObjectId(),
origin: shortUrl,
destination: destination,
}).then(() => {
// Unique Id
res.json(shortUrl);
});
});
Before creating a new entry you can check work destination with
const existing = await UrlSchema.findOne({destination:req.body.destination});
if(!existing){
// create new
} else{
// return same
}
This way you will be creating destination if it does not exist already. You can remove tariling slash(/) if it exists to match URLs better,
You've listed four slightly different URLs:
https://www.google.com
https://google.com
https://www.google.com/
https://google.com/
None of these are technically the same https request, though it sounds like you want to assume that the / at the end is optional and thus does not make it a different target URL.
The last two are not guaranteed to be the same host as the first two. For google.com and www.google.com, they are the same host, but this is not guaranteed to be the case for all possible hosts.
If you want to assume that these four are all to the same host no matter what the domain is, then you just have to normalize the URL before you put it in your database and then before assigning a new shortened ID, you search the database for the normalized version of the URL.
In this case, you would remove the www. and remove any trailing slash to create the normalized version of the URL.
function normalizeUrl(url) {
// remove "www." if at first part of hostname
// remove trailing slash
return url.replace(/\/\/www\./, "//").replace(/\/$/, "");
}
Once you've normalized the URL, you search for the normalized URL in your database. If you find it, you use the existing shortener for it. If you don't find it, you add the normalized version to your database with a newly generated shortId.
Here's a demo:
function normalizeUrl(url) {
// remove "www." if at first part of hostname
// remove trailing slash
return url.replace(/\/\/www\./i, "//").replace(/\/$/, "");
}
const testUrls = [
"https://www.google.com",
"https://www.google.com/",
"https://google.com",
"https://google.com/",
];
for (const url of testUrls) {
console.log(normalizeUrl(url));
}
FYI, since hostnames in DNS are not case sensitive, you may also want to force the hostname to lower case to normalize it. Path names or query parameters could be case sensitive (sometimes they are and sometime they are not).
To include the host case sensitivity normalization, you could use this:
function normalizeUrl(url) {
// remove "www." if at first part of hostname
// remove trailing slash
// lowercase host name
return newUrl = url.replace(/\/\/www\./i, "//").replace(/\/$/, "").replace(/\/\/([^/]+)/, function(match, p1) {
// console.log(match, p1);
return "//" + p1.toLowerCase();
});
}
const testUrls = [
"https://www.google.com",
"https://www.google.com/",
"https://google.com",
"https://google.com/",
"https://WWW.google.com",
"https://www.Google.com/",
"https://GOOGLE.com",
"https://google.COM/",
"https://www.Google.com/xxx", // this should be unique
"https://google.COM/XXX", // this should be unique
];
for (const url of testUrls) {
console.log(normalizeUrl(url));
}
I'm trying to figure out how to parse a form entry to set the model attribute to something else; e.g., extracting the video ID of a youtube video from a URL input. Is there a way to use parsers/formatters (6.21 features?) to accomplish this easily? I hoped to find a good example for this, and maybe there is one somewhere, but perhaps this would make a good one if there's not.
Here is a working example of what I'm attempting to accomplish, but in multiple steps and without the use of parsers. Any help adapting the code to set model.videoID from a URL in a single step (or fewer than 3 steps, at least) would be very appreciated. Thank you for your help with this and my other past questions. :)
Wow, this was much easier than I expected to implement. Here is the modification of the JS Bin which uses parsers, recently added with angular-formly#6.21.0, to extract the video ID from a YouTube URL in one function. It also, conveniently, validates itself!
Here is the relevant code, to summarize:
{
key: 'vidid',
type: 'input',
parsers: [extractID],
templateOptions: {
label: 'YouTube Video',
placeholder: 'Insert video URL here'
},
...
function extractID(value) {
if (value != undefined || value != '') {
var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
var match = value.match(regExp);
if (match && match[2].length == 11) {
return match[2];
}
}
};
I have an app that is loading URLs into a WebView (x-ms-webview). When the user makes the request, I would like to compare the URL they are trying to load with the "whitelisted" URLs in the ApplicationContentUriRules and warn them if it is not there. Any ideas how I might accomplish this?
There isn't a direct API for pulling information out of the manifest, but there are options.
First, you can just maintain an array of those same URIs in your code, because to change them you'd have to change the manifest and update your package anyway, so you would update the array to match. This would make it easy to check, but increase code maintenance.
Such an array would also let you create a UI in which the user can enter only URIs that will work, e.g. you can offer possibilities from a drop-down list instead of letting the user enter anything.
Second, you can read the manifest XML into a document directly and parse through it to get to the rules. Here's some code that will do that:
var uri = new Windows.Foundation.Uri("ms-appx:///appxmanifest.xml");
var doc;
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function (file) {
return Windows.Storage.FileIO.readTextAsync(file);
}).done(function (text) {
doc = new Windows.Data.Xml.Dom.XmlDocument();
doc.loadXml(text);
var acur = doc.getElementsByTagName("ApplicationContentUriRules");
if (acur !== null) {
var rules = acur[0].getElementsByTagName("Rule");
for (var i = 0; i < rules.length; i++) {
console.log(rules[i].getAttribute("Match") + " - " + rules[i].getAttribute("Type"));
}
}
});
You could probably just get "Rule" tags directly from the root doc, because I don't think anything else in the manifest uses that kind of node, but to future-proof it's better to get the ApplicationContentUriRules first. As you can see, the "Match" attribute is what holds the URI for that rule, but you also need to make sure that "Type" is "include" and not "exclude".
I'm displaying a list of articles in a page that are fetched using the Ember Data RESTAdapter. I need to implement a bootstrap'esque paginator (see: http://twitter.github.com/bootstrap/components.html#pagination) and cant seem to find a sane pattern for returning pagination data such as, page count, article count, current page, within a single request.
For example, I'd like the API to return something like:
{
articles: [{...}, {...}],
page: 3,
article_count: 4525,
per_page: 20
}
One idea was to add an App.Paginator DS.Model so the response could look like:
{
articles: [{...}, {...}],
paginator: {
page: 3,
article_count: 4525,
per_page: 20
}
}
But this seems like overkill to hack together for something so trivial. Has anyone solved this problem or found a particular pattern they like? Is there a simple way to manage the RESTAdapter mappings to account for scenarios such as this?
Try to use Ember Pagination Support Mixin and provide your own implementation of the following method. Instead of loading all the content, you can fetch the required content when the user is navigating the pages. All what you need initially is the total account of your records.
didRequestRange: function(rangeStart, rangeStop) {
var content = this.get('fullContent').slice(rangeStart, rangeStop);
this.replace(0, this.get('length'), content);
}
With ember-data-beta3 you can pass a meta-property in your result. The default RESTSerializer looks for that property and stores it.
You can access the meta-data like this:
var meta = this.get("store").metadataFor("post");
If you are not able to change the JSON returned from the server you could override the extractMeta-hook on the ApplicationSerializer (or any other Model-specific serializer).
App.ApplicationSerializer = DS.RESTSerializer.extend({
extractMeta: function(store, type, payload) {
if (payload && payload.total) {
store.metaForType(type, { total: payload.total }); // sets the metadata for "post"
delete payload.total; // keeps ember data from trying to parse "total" as a record
}
}
});
Read more about meta-data here
I am using Struts 2 and want to include an editable server side paging and sorting grid.
I need to sublclass the QueryReadStore to implement the write and notification APIs. I do not want to inlcude server side REST services so i do not want to use JsonRest store. Any idea how this can be done.? What methods do i have to override and exactly how. I have gone through many examples but i am not getting how this can be done exactly.
Also is it possible to just extend the ItemFileWriteStore and just override its methods to include server side pagination? If so then which methods do i need to override. Can i get an example about how this can be done?
Answer is ofc yes :)
But do you really need to subclass ItemFileWriteStore, does it not fit your needs? A short explaination of the .save() follows.
Clientside does modify / new / delete in the store and in turn those items are marked as dirty. While having dirty items, the store will keep references to those in a has, like so:
store._pending = { _deletedItems: [], _modifiedItems: [], _newItems: [] };
On call save() each of these should be looped, sending requests to server BUT, this does not happen if neither _saveEverything or _saveCustom is defined. WriteStore simply resets its client-side revert feature and saves in client-memory.
See source search "save: function"
Here is my implementation of a simple writeAPI, must be modified to use without its inbuilt validation:
OoCmS._storeAPI
In short, follow this boiler, given that you would have a CRUD pattern on server:
new ItemFileWriteStore( {
url: 'path/to/c**R**ud',
_saveCustom: function() {
for(var i in this._pending._newItems) if(this._pending._deletedItems.hasOwnProperty(i)) {
item = this._getItemByIdentity(i);
dxhr.post({ url: 'path/to/**C**rud', contents: { id:i }});
}
for(i in this._pending._modifiedItems) if(this._pending._deletedItems.hasOwnProperty(i)) {
item = this._getItemByIdentity(i);
dxhr.post({ url: 'path/to/cr**U**d', contents: { id:i }});
}
for(i in this._pending._deletedItems) if(this._pending._deletedItems.hasOwnProperty(i)) {
item = this._getItemByIdentity(i);
dxhr.post({ url: 'path/to/cru**D**', contents: { id:i }});
}
});
Now; as for paging, ItemFileWriteStore has the pagination in it from its superclass mixins.. You just need to call it with two setups, one being directly on store meaning server should only return a subset - or on a model with query capeabilities where server returns a full set.
var pageSize = 5, // lets say 5 items pr request
currentPage = 2; // note, starting on second page (with *one* being offset)
store.fetch({
onComplete: function(itemsReceived) { },
query: { foo: 'bar*' }, // optional filtering, server gets json urlencoded
count: pageSize, // server gets &count=pageSize
start: currentPage*pageSize-pageSize // server gets &start=offsetCalculation
});
quod erat demonstrandum