Skip to content
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

Remote data #494

Merged
merged 38 commits into from Oct 29, 2018
Merged

Remote data #494

merged 38 commits into from Oct 29, 2018

Conversation

RealOrangeOne
Copy link
Contributor

@RealOrangeOne RealOrangeOne commented Oct 20, 2018

Fixes #476.
Re-implements #465
Extends #379

Allow loading data from remote endpoints, and parsing through the existing formats load_data supports.

This PR is intentionally designed to reuse as much of the code as possible when reading from data files or remote endpoints. This not only reduces the chance of odd bugs appearing, but means I don't have to write as much! Because I also moved things out into separate files, GitHub makes it looks like i've done way more work than I actually have.

  • Support requesting remote data
  • Allow loading data as plain text, with no parsing
  • Implement a cache to reduce repeat API calls / parsing
  • Move data loading into separate file to split it out, it's quite a lot of code!
  • Send the current version of zola in the user agent. There's no reason for this, I just thought it might be nice!
  • Rename kind argument format, as it's more appropriate
  • If someone tries to load files from outside their site directory, throw an error. This should also include symlinks

It would be possible to edit the headers when sending / receiving a response with the format argument. But i decided not to do that, and we / someone else can add it further down the line.

None of this code has been run through rustfmt, intentionally.

Note: Currently the test can_load_remote_data is failing, when it shouldn't be. This will fix itself once the repo move occurs.

cc @kellpossible, enjoy!

@RealOrangeOne
Copy link
Contributor Author

(Netlify is failing because it can't find the new function, which is to be expected)

components/templates/src/lib.rs Outdated Show resolved Hide resolved
components/templates/Cargo.toml Outdated Show resolved Hide resolved
components/templates/Cargo.toml Outdated Show resolved Hide resolved
components/templates/Cargo.toml Outdated Show resolved Hide resolved
components/templates/src/global_fns/load_data.rs Outdated Show resolved Hide resolved
"toml" => load_toml(data),
"csv" => load_csv(data),
"json" => load_json(data),
"plain" => to_value(data).map_err(|e| e.into()),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about plain, what is it even loading?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plain is just the format which returns the data raw, with no additional processing. Either the request body or the file contents.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but when is it needed? I can't really think of a usecase where you would want that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There probably are some use cases out there, and seeing as it was basically free to implement, thought I might as well. It's probably something which may be critical to someone out there

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a heads up - I actually would make use of plain to load CSS and shove it inline at build-time, or to load a base64-encoded value that's ugly in code but needs to exist. They're rare use cases but they do exist.

components/templates/src/global_fns/load_data.rs Outdated Show resolved Hide resolved
components/utils/src/fs.rs Outdated Show resolved Hide resolved
docs/content/documentation/templates/overview.md Outdated Show resolved Hide resolved
docs/templates/index.html Outdated Show resolved Hide resolved
@RealOrangeOne
Copy link
Contributor Author

@Keats I've made all the requested changes, and a couple bits of cleanup.

Copy link
Collaborator

@Keats Keats left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple more comments but looking good!

Cargo.toml Outdated Show resolved Hide resolved
enum OutputFormat {
TOML,
JSON,
CSV,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't uppercase them even if they are acronyms to be consistent with Rust style (https://doc.rust-lang.org/1.0.0/style/style/naming/README.html)

TOML,
JSON,
CSV,
Plain
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would still remove that for now, it can be added later if necessary

}

impl OutputFormat {
fn from(output_format: String) -> Result<Self> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could impl FromStr instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did think of that, but because it's possible for it to fail (ie the string doesnt match one of the enum values), it's unsafe, and TryFrom is only in nightly right now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FromStr returns a Result though? FromStr and TryFrom look to be identical for this usecase

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, I found my confusion. I was looking at From rather than FromStr. Yes you're right, FromStr would be ideal to implement here!

}
}

fn get_cache_key(data_source: &DataSource, format: &OutputFormat) -> u64 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making this part of the impl of DataSource would be cleaner imo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was toying with where to put it, as it's also equally valid on OutputFormat, but as most of the computation varys for DataSource, I guess there makes the most sense of the 2.

{{ response }}
```

By default, the response body will be returned with no parsing. This can be changed by using the `format` argument as above.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I guess we need plain because of that? How about making the format argument mandatory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could make it mandatory, but the fact it bases it off the file extension is a really nice touch for local data files. Having to specify that my data.json file is a JSON file feels unnecessary when it's so easy to guess from the file extension, and change it by default if required.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure myself what is the best choice there. I kind of like the nice UX for ending in JSON but in practice for remote data you will need to specify the format so it feels a bit like it could surprise the end user when something works for local data but not remote.

I would tend towards removing the special casing but not 100% convinced.

@Keats
Copy link
Collaborator

Keats commented Oct 29, 2018

The 2 failing tests need to be fixed but I can merge it after

We cant use a fixed hash because it's based on the absolute path, which
changes for each dev (probably)
@RealOrangeOne
Copy link
Contributor Author

I've fixed the tests, and they run fine locally, however seem to be doing odd things on Travis.

@Keats
Copy link
Collaborator

Keats commented Oct 29, 2018

For global_fns::load_data::tests::fails_when_request_404s, you can make up a random URL to avoid issues like that.
For the other, you can use a fake public api like https://jsonplaceholder.typicode.com/todos/1 to avoid 403 and various issues

@RealOrangeOne
Copy link
Contributor Author

Tests passing 🎉 (besides netlify, but that doesn't look related to this PR?)

@Keats
Copy link
Collaborator

Keats commented Oct 29, 2018

Netlify is not going to work for a while with Zola sadly, not related to your PR :)

Thanks!

@Keats Keats merged commit aad12d8 into getzola:next Oct 29, 2018
@RealOrangeOne RealOrangeOne deleted the remote-data branch October 29, 2018 20:19
@kellpossible
Copy link
Contributor

Nice one @RealOrangeOne !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants